在挖掘网络之后,我发现了一些关于利用 CRTP 允许在运行时实例化静态成员的强大模式的参考:
等等。建议的方法效果很好,除非将此类层次结构放入外部库中。这样做,运行时初始化不再起作用,除非我在派生类的头文件中手动#include。但是,这违背了我的主要目的 - 无需更改其他源文件即可向我的应用程序添加新命令。
一些代码,希望对您有所帮助:
class CAction
{
protected:
// some non relevant stuff
public:
// some other public API
CAction(void) {}
virtual ~CAction(void) {}
virtual std::wstring Name() const = 0;
};
template <class TAction>
class CCRTPAction : public CAction
{
public:
static bool m_bForceRegistration;
CCRTPAction(void) { m_bForceRegistration; }
~CCRTPAction(void) { }
static bool init() {
CActionManager::Instance()->Add(std::shared_ptr<CAction>(new TAction));
return true;
}
};
template<class TAction> bool CCRTPAction<TAction>::m_bForceRegistration = CCRTPAction<TAction>::init();
以这种方式完成的实现:
class CDummyAction : public CCRTPAction<CDummyAction>
{
public:
CDummyAction() { }
~CDummyAction() { }
std::wstring Name() const { return L"Dummy"; }
};
最后,这里是容器类 API:
class CActionManager
{
private:
CActionManager(void);
~CActionManager(void);
std::vector<std::shared_ptr<CAction>> m_vActions;
static CActionManager* instance;
public:
void Add(std::shared_ptr<CAction>& Action);
const std::vector<std::shared_ptr<CAction>>& AvailableActions() const;
static CActionManager* Instance() {
if (nullptr == instance) {
instance = new CActionManager();
}
return instance;
}
};
在单个项目解决方案中一切正常。但是,如果我将上面的代码放在单独的 .lib 中,魔法就会以某种方式中断,并且DummyAction
不再实例化实现类(等等)。
我看到#include "DummyAction.h"
某个地方,无论是在我的库中还是在主项目中,都可以使事情正常进行,但是
- 对于我们的项目,添加动作不需要更改其他文件是强制性的。
- 我真的不明白幕后发生了什么,这让我很不舒服。我真的很讨厌依赖我不完全掌握的解决方案,因为错误可能会在任何时间、任何时间、可能在将我们的软件交付给客户的前一天出现 :)
- 更奇怪的是,将
#include
指令而不是定义构造函数/析构函数放在头文件中仍然会破坏魔法。
谢谢大家的关注。我真的希望有人能够阐明一些光...