有什么方法可以在抽象基类中使用模板函数吗?

时间:2011-12-23 01:18:20

标签: c++ virtual abstract-class

我正在尝试创建一个配置管理器类,它可以通过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。

最好的方法是什么?

3 个答案:

答案 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的最佳答案是(部分)为什么我认为这几乎是你所能做的。