请考虑以下简化示例:
#include "boost/shared_ptr.hpp"
#include "boost/smart_ptr/enable_shared_from_this.hpp"
using namespace boost;
class State : public boost::enable_shared_from_this<State>
{
public:
shared_ptr<State> GetSelf()
{
return shared_from_this();
};
// returns following state
virtual shared_ptr<State> Execute() = 0;
};
template<typename T>
shared_ptr<T> Create()
{
return shared_ptr<T>(new T);
}
class MyState2;
class MyState1 : public State
{
virtual shared_ptr<State> Execute()
{
if (change of state)
return Create<MyState2>();
else
return GetSelf();
};
};
class MyState2 : public State
{
virtual shared_ptr<State> Execute()
{
if (change of state)
return Create<MyState1>();
else
return GetSelf();
};
};
int main(int argc, char* argv[])
{
shared_ptr<State> pCurrentState = Create<MyState1>(); // <-- OK
// State* pCurrentState(new MyState1); // <-- Runtime error
while (...)
pCurrentState = pCurrentState->Execute();
return 0;
}
State 类是“框架”的一部分。它是轻量级状态机中用户定义状态的基础,其中每个状态返回其跟随者状态。如果状态没有改变,它会返回自己。框架用户可以任意派生自类 State。显然不允许创建派生类的“不受控制”实例(如果调用 GetSelf() 将导致运行时错误)。为了将用户指向正确的方向,提供了一个 Create() 函数模板来创建“受控”实例。由于我想尽可能地使用法万无一失,我如何才能确保用户不会创建任何不受 shared_ptr 控制的派生状态的实例?或者至少给出一个有意义的错误信息(在编译时?)如果他这样做了。
感谢您的帮助!
最佳答案
防止非托管实例的最简单方法是将每个派生类的构造函数设为私有(private)。您的工厂函数需要是它正在创建的类的友元或成员;如果您想保留工厂模板,则需要在派生类之前声明它,以便使其成为 friend :
template<typename T>
shared_ptr<T> Create()
{
return shared_ptr<T>(new T);
}
class Derrived : public Base
{
private:
friend shared_ptr<Derrived> Create<Derrived>();
Derrived() {}
// Client implementation goes here
};
但是,我通常建议您不要强制以特定方式管理类。如果类本身要求它们由共享指针管理以便正常运行(也就是说,它们需要调用 shared_from_this()
从他们的成员函数出于某种原因)。否则,只需组织您的框架,使其使用共享指针,任何使用该框架的人都必须这样做,而无需奇怪的强制机制。根本不需要 GetSelf()
,因为如果您完全可以访问一个对象,您将始终有一个共享指针可供复制,并且不需要 enable_shared_from_this
除非类需要在内部访问共享指针(这是一件很不寻常的事情)。
更新:在您的用例中,我认为基类不可能强制使用共享指针(但如果我错了请纠正我)。在调用需要它们的函数时强制使用共享指针可能是有意义的。您将能够创建非托管对象,但不能对它们进行任何危险的操作。
class State : public boost::enable_shared_from_this<State>
{
public:
// returns following state
friend shared_ptr<State> Execute(shared_ptr<State> state) {
return state->Execute();
}
private:
virtual shared_ptr<State> Execute() = 0;
};
class MyState : public State
{
shared_ptr<State> Execute() {return shared_from_this();}
};
int main(int argc, char* argv[])
{
shared_ptr<State> state1(new MyState); // <-- OK
State * state2(new MyState); // <-- OK, but can't be used
Execute(state1); // <-- OK
// Execute(state2); // <-- Error
// state2->Execute(); // <-- Error
}
关于c++ - 安全的 enable_shared_from_this 用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7803789/