Я не слежу за вашим вопросом на 100%, но здесь идет ...
Единственное, что я могу придумать для # 5, это сделать Command::execute
частным / защищенным и сделать Manager
friend
из Command
. Недостатком этого подхода является то, что вы теперь ввели зависимость от Command
до Manager
.
Что касается # 6, если shared_ptr<const Foo>
объекты пользователя были получены из коллекции shared_ptr<Foo>
менеджера, то Manager
должен быть в состоянии безопасно const_pointer_cast shared_ptr<const Foo*>
вернуться в shared_ptr<Foo*>
. Если Менеджер попытается создать shared_ptr<const Foo*>
, где указатель является фактическим постоянным объектом, вы получите неопределенное поведение.
Я думал о другом решении для # 5:
Определите класс ExecutableCommand
, полученный из Command
. ExecutableCommand
имеет добавленный метод для вызова команды, который будет использоваться только Manager
. Клиенты могут получить доступ к ExecutableCommand
объектам только через указатели / ссылки на Command
. Когда менеджер хочет вызвать Command
, он понижает его до ExecutableCommand
, чтобы получить доступ к интерфейсу вызова.
Рабочий пример (включая const_pointer_cast для # 6):
#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;
}