从模板化类中重写纯虚函数

时间:2014-02-10 16:37:04

标签: c++ templates inheritance abstract-class pure-virtual

我已经搜索了堆栈溢出但是没有找到能完全回答我的问题的东西。我有一个接口类,它只包含纯虚函数,我希望由派生自这个类的类实现。

我有一个接口,我将调用 BaseInterface ,它定义了我希望在从该接口派生的所有类中重写的函数。在这个例子中,假设只有一个名为 toImplement 的纯虚函数。我创建了一个名为 Base 的类,它继承自 BaseInterface ,并为继承的纯虚函数添加了一些功能。 Base仍然是一个抽象类,因为它没有实现 BaseInterface 中的函数。

我有几个派生自 Base 的类,它们都受益于 Base 的常用功能,但指定运行 toImplement 时会发生什么他们的实例。这些类应该都是具体的,并满足 BaseInterface 设置的所有要求。下面我定义了一个名为 Derived 的类。

当BaseInterface和Base没有模板化时,所有这些都可以正常工作。代码编译并运行正常,无需在 Base 中定义(1.)或实现(2.) toImplement

但是我希望 toImplement 能够使用不同的类型。根据我的理解,在模板化的类中使用纯虚函数是很好的。我在某些类型T上模板 BaseInterface Base 。当我没有在 Base 中定义 toImplement 时(1。 ),我无法编译,因为Base不知道在 tryUsingImplemented 中使用哪个 toImplement 。如果我现在将定义添加到 Base ,则代码会预编译,但链接器无法找到Base :: toImplement的实现。最后,如果我在 Base (1.和2.)中定义并实现 toImplement ,代码就会编译。

我不喜欢这个,因为我在Base中有一个 toImplement 的虚拟实现,我从不希望运行这个实现。此外,由于基础实施 toImplement ,因此不再需要派生来实施它。这使得 BaseInterface 在我眼中无用。

可以让我了解如何在派生中强制执行 toImplement ,而不必先在 Base 中实现它,如果是在可能的情况下?

template <typename T>
class BaseInterface {
   virtual void toImplement(T & t) = 0;
};


template <typename T>
class Base : public BaseInterface<T> {
bool m_useImplemented;

public:
   explicit Base(bool useImplemented) : m_usedImplemented(useImplemented) {}

   void tryUsingImplemented(T & t) {
      if (m_useImplemented)
         toImplement(t);
   }  

protected:
   // 1: Defining toImplement pure virtual function in Base
   virtual void toImplement(T & t);
};

// 2. Implementing a version of toImplement in Base which does nothing
template <typename T>
inline void Base<T>::toImplement(T & t) {
   // do nothing
}

class Derived : public Base<int> {
public:
   explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}

protected:
   // 3. implementing toImplement in Derived 
   void toImplement(T & t) {
      std::cout << "Doing stuff for Derived" << std::endl;
   }  

};

2 个答案:

答案 0 :(得分:3)

为了将来参考,如果您提供了编译器错误消息,将会很有帮助。

然而,在这种情况下,我知道。您的代码中有两个错误:

  1. toImplementBaseInterface中是私有的。
  2. tryUsingImplemented中的查找不会查找基类。您遇到了lookup in dependent bases问题。要解决此问题,请写下this->toImplement(t)

答案 1 :(得分:0)

如果您打算从派生类中调用它,则需要在toImplement中将protected声明为BaseInterface。我已从派生类中删除了所有重写方法,并将Derived::toImplement的参数类型替换为int,并且编译良好。后者是必要的,因为Derived不是模板,因此您需要使用传递给Base的模板参数。

  #include <iostream>

  template <typename T>
  class BaseInterface {
  protected:
     virtual void toImplement(T & t) = 0;
  };


  template <typename T>
  class Base : public BaseInterface<T> {
  bool m_useImplemented;

  public:
     explicit Base(bool useImplemented) : m_useImplemented(useImplemented) {}

     void tryUsingImplemented(T & t) {
        if (m_useImplemented)
           toImplement(t);
     }  
  };

  class Derived : public Base<int> {
  public:
     explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}

  protected:
     // 3. implementing toImplement in Derived 
     void toImplement(int & t) {
        std::cout << "Doing stuff for Derived" << std::endl;
     }  

  };