我没有100%关注你的问题,但是这里......
对于#5 ,我唯一能想到的就是将Command::execute
私有/受保护Manager
和friend
. Command
这种方法的缺点是您现在已经引入了从Command
to的依赖关系Manager
。
至于 #6,如果用户的shared_ptr<const Foo>
对象来自 Manager 的shared_ptr<Foo>
集合,那么Manager
应该能够安全地将 const_pointer_castshared_ptr<const Foo*>
重新转换为shared_ptr<Foo*>
. 如果 Manager 尝试 const cast a shared_ptr<const Foo*>
,其中指针对象是实际的常量对象,您将获得未定义的行为。
我想到了#5的另一种解决方案:
定义一个ExecutableCommand
类,派生自Command
. ExecutableCommand
有一个调用命令的附加方法,仅供Manager
. 客户端只能ExecutableCommand
通过指针/引用访问对象Command
。当 Manager 想要调用 aCommand
时,它会将其向下转换为 aExecutableCommand
以获得对调用接口的访问权限。
工作示例(包括#6 的 const_pointer_cast):
#include <iostream>
#include <string>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost;
//------------------------------------------------------------------------------
struct Foo
{
Foo(int x) : x(x) {}
void print() {++x; cout << "x = " << x << "\n";} // non-const
int x;
};
//------------------------------------------------------------------------------
struct Command
{
// Interface accessible to users
std::string name;
private:
virtual void execute() = 0;
};
//------------------------------------------------------------------------------
struct ExecutableCommand : public Command
{
// Only accessible to Manager
virtual void execute() {} // You may want to make this pure virtual
};
//------------------------------------------------------------------------------
struct PrintCommand : public ExecutableCommand
{
PrintCommand(shared_ptr<const Foo> foo)
: foo_( const_pointer_cast<Foo>(foo) ) {}
void execute() {foo_->print();}
private:
shared_ptr<Foo> foo_;
};
//------------------------------------------------------------------------------
struct Manager
{
void execute(Command& command)
{
ExecutableCommand& ecmd = dynamic_cast<ExecutableCommand&>(command);
ecmd.execute();
}
void addFoo(shared_ptr<Foo> foo) {fooVec.push_back(foo);}
shared_ptr<const Foo> getFoo(size_t index) {return fooVec.at(index);}
private:
std::vector< shared_ptr<Foo> > fooVec;
};
//------------------------------------------------------------------------------
int main()
{
Manager mgr;
mgr.addFoo( shared_ptr<Foo>(new Foo(41)) );
Command* print = new PrintCommand(mgr.getFoo(0));
// print.execute() // Not allowed
mgr.execute(*print);
delete print;
}