多重继承纯基函数

Posted

技术标签:

【中文标题】多重继承纯基函数【英文标题】:multiple inheritance pure base functions 【发布时间】:2014-04-26 18:58:56 【问题描述】:

为什么这不起作用?虚函数GetNOperands()PerformOp()在BinaryOp类中定义,DoOp()在OpAdd类中定义。操作符类中的虚拟Prec() 函数也在 OpAdd 中定义。我研究了我认为不适用于此代码的“钻石问题”,因为派生类中的每个函数只有一个定义?代码如下:

#include <iostream>
#include <vector>
#define PREC_LOW 0
#include <assert.h>

//operator class - abstract
template <class T>  class Op 
public:
    virtual unsigned int GetNOperands() = 0;
    virtual bool PerformOp( std::vector<T>& operands, T& result ) = 0;
    virtual ~Op() 
;

//binary operator class - for 2 operators - abstract
template <class T> class BinaryOp : public Op<T> 
public:
    unsigned int GetNOperands();
    bool PerformOp(  std::vector<T>& operands, T& result );
    virtual ~BinaryOp() 
protected:
    virtual bool DoOp( T first, T second, T& result ) = 0;
;

template <class T> class Operator : public Op<T> 
public:
    virtual unsigned int Prec() = 0;    //precedence
;

template <class T> class OpAdd : public BinaryOp<T>, public Operator<T> 
public:
    unsigned int Prec();
private:
    bool DoOp( T first, T second, T& result );
;

template <class T> unsigned int BinaryOp<T>::GetNOperands() 
    return 2;

template <class T> bool BinaryOp<T>::PerformOp(  std::vector<T>& operands, T& result ) 
    assert( operands.size() == 2 );
    return DoOp( operands.at(0),operands.at(1),result);

template <class T> bool OpAdd<T>::DoOp( T first, T second, T& result ) 
    result = first + second;
    return true;

template <class T> unsigned int OpAdd<T>::Prec() 
    return PREC_LOW;


int main() 
    OpAdd<int> a;
    return 0;

编辑: 编译器错误状态:

source.cpp: In function 'int main()':
source.cpp:55:13: error: cannot declare variable 'a' to be of abstract type 'OpAdd<int>'
  OpAdd<int> a;
             ^
source.cpp:30:29: note:   because the following virtual functions are pure withi
n 'OpAdd<int>':
 template <typename T> class OpAdd : public BinaryOp<T>, public Operator<T> 
                             ^
source.cpp:10:23: note:         unsigned int Op<T>::GetNOperands() [with T = int]
  virtual unsigned int GetNOperands() = 0;
                       ^
source.cpp:11:15: note:         bool Op<T>::PerformOp(std::vector<T>&, T&) [with T = int]
  virtual bool PerformOp( std::vector<T>& operands, T& result ) = 0;

【问题讨论】:

定义“不起作用”。 好吧,您没有覆盖OpAdd 中的direct 基类Operator&lt;T&gt;(及其基类)的虚函数。 我添加了编译错误 请阅读:不能声明抽象类型的变量/由于这些纯函数是抽象的...编译器正在拼出究竟是什么错误。 但是这些函数是在 BinaryOp 中定义的,是被 OpAdd 继承的? 【参考方案1】:

OpAdd&lt;&gt; 继承了BinaryOp&lt;&gt;,也继承了Operator&lt;&gt;,它们都是抽象的。如果您删除不必要的和模棱两可的后者继承,它应该编译。

template <class T> class OpAdd : public BinaryOp<T> 
public:
    unsigned int Prec();
private:
    bool DoOp( T first, T second, T& result );
;

另一种可能是避免同时定义Operator&lt;&gt;::Prec() 的最佳方法是将继承设置为Op&lt;&gt; 虚拟,例如live demo

template <class T> class BinaryOp : public virtual Op<T>
...
template <class T> class Operator : public virtual Op<T>
....

【讨论】:

【参考方案2】:

错误消息告诉您问题出在哪里——通过AddOp&lt;T&gt;Operator&lt;T&gt; 基继承的GetNOperands 方法是抽象的。由于这是与BinaryOp&lt;T&gt; 基不同的基(有两个不同的Op&lt;T&gt; 基彼此无关),因此函数在基类的另一个实例中定义的事实是无关紧要的。

您有两种解决方法的选择:

    将所有公共基类设为virtual,以便它们引用同一个基实例,而不是每次继承时都创建一个新实例。这使得继承以一种合理的方式工作(它在任何其他语言中的工作方式)

    仅使用单一继承——每个类只能(直接)从一个基类继承。这样可以避免生成多个基类实例。

【讨论】:

以上是关于多重继承纯基函数的主要内容,如果未能解决你的问题,请参考以下文章

多重继承,虚基类

继承受保护函数和公共变量 C++ 的多重继承编译错误

多重继承,虚继承,MI继承中虚继承中构造函数的调用情况

python super()函数的用法与多重继承

当在其层次结构中具有菱形继承的类的多重继承时,函数的模糊继承

具有相同名称的函数的类中的多重继承[重复]