私はあなたの質問に 100% 従っているわけではありませんが、ここでは...
#5について私が考えることができる唯一のことは、Command::execute
プライベート/プロテクトを作成し、のを作成Manager
することfriend
ですCommand
. このアプローチの欠点は、依存関係を からCommand
に導入したことManager
です。
#6 に関しては、ユーザーのshared_ptr<const Foo>
オブジェクトが Manager のshared_ptr<Foo>
コレクションから生成されたものである場合、 const_pointer_cast を安全に に戻すことができるはずManager
です。Managerが、参照先が実際の定数オブジェクトであるa を const キャストしようとすると、未定義の動作が発生します。shared_ptr<const Foo*>
shared_ptr<Foo*>
shared_ptr<const Foo*>
#5の別の解決策を考えました:
ExecutableCommand
から派生したクラスを定義しCommand
ます。ExecutableCommand
によってのみ使用される、コマンドを呼び出すメソッドが追加されていManager
ます。クライアントは、へExecutableCommand
のポインタ/参照を介してのみオブジェクトにアクセスできますCommand
。Manager が を呼び出したい場合、Command
それを にダウンキャストしてExecutableCommand
、呼び出しインターフェースへのアクセスを取得します。
作業例 (#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;
}