我正在尝试创建一个配置管理器类,它可以通过std :: string存储任意对象。
我的界面(抽象基类)的开始是这个(当然这非常不完整)
class ConfigurationManager
{
public:
static boost::shared_ptr<ConfigurationManager> create();
template<typename T>
virtual T getOption(const std::string& name) = 0;
};
然后我的编译器指出模板不能是虚拟的(然后我意识到我不能导出模板)。
在内部我将使用boost :: any(几乎是运行时检查的void *),但我不想在我的界面中暴露boost :: any。
最好的方法是什么?
答案 0 :(得分:7)
使受保护的虚拟抽象函数返回boost::any
,并使非虚拟的非抽象公共模板函数将其隐藏在界面用户之外。
class ConfigurationManager {
protected:
virtual boost::any getOptionProtected(const std::string& name) = 0;
public:
static boost::shared_ptr<ConfigurationManager> create();
template<typename T> T getOption(const std::string& name) {
return boost::any_cast<T>(getOptionProtected(name));
}
};
答案 1 :(得分:4)
另一种方法是将派生类型的名称传递给ConfigurationManager
:
template<typename Derived>
class ConfigurationManager
{
public:
static boost::shared_ptr<ConfigurationManager> create();
template<typename T>
T getOption(const std::string& name)
{
// call Derived::getOption
return static_cast<Derived*>(this)->getOption(name);
}
};
派生类型Foo
将如下定义:
class Foo : public ConfigurationManager<Foo>
{
template<typename T>
T getOption(const std::string& name)
{
// do something Foo-specific here
}
};
最终结果类似于抽象虚函数。这个成语被称为curiously recurring template pattern。
答案 2 :(得分:1)
我不知道boost::any
为你做了什么,但除此之外你的(仅我认为)选项是1)使ConfigurationManager
成为模板类,或者2)make {{ 1}} 非 -virtual但使用单独的非模板虚拟函数(在ConfigurationManager::getOption
内调用)来管理派生类中所需的功能。 2)上还有变体,例如包括指向对象的指针,该对象指定(非虚拟)getOption
的预期功能。该对象将是一个类的实例,它本身是继承层次结构的一部分 - 基本上是策略模式。虽然看起来更复杂。所以基本上我建议
getOption
this SO thread的最佳答案是(部分)为什么我认为这几乎是你所能做的。