关于c ++:从模板化类中重写纯虚函数

Overriding a pure virtual function from templated classes

我已经搜索了堆栈溢出,但没有找到确切回答我问题的内容。我有一个接口类,它只包含纯虚拟函数,我希望通过从这个类派生的类来实现这些函数。

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

我有几个类派生自BASE,这些类都受益于BASE的公共功能,但是指定在实例上运行ToImplement时会发生什么。这些类都应该是具体的,并且满足BaseInterface设置的所有要求。下面我定义一个叫做派生的类。

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

不过,我希望实现与不同的类型一起工作。据我所知,在模板类中使用纯虚拟函数是很好的。我将baseinterface模板化,并基于某种类型t。当我在base(1)中不定义实现时,我无法编译,因为base不知道在TryusingImplemented中使用哪个实现。如果我现在将定义添加到基中,代码将预编译,但链接器找不到基::ToImplement的实现。最后,如果我在基础(1)中定义和实现了实现。代码编译。

我不喜欢这样,因为我在基中有一个toimplement的虚拟实现,我从不希望运行这个实现。此外,由于基实现了ToImplement,因此不再需要派生来实现它。这让我觉得BaseInterface没用。

Sombody能否告诉我如何在派生中强制实现ToImplement,而不必首先在基中实现它(如果可能的话)?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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;
   }  

};


如果您提供了编译器错误消息,这将有助于以后的参考。

不过,在这种情况下,我知道。代码中有两个错误:

  • toImplementBaseInterface中是私有的。
  • tryUsingImplemented中的查找将不在基类中查找。你正面临着依赖基问题中的查找。要修复它,请写入this->toImplement(t)

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
      #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;
         }  

      };