为什么不从不同的继承分支覆盖纯虚方法?

时间:2016-07-06 18:26:59

标签: c++ c++11 virtual-method linearization

我有这个,也许是一个复杂的类层次结构:

class BS {
  public:
    virtual void meth()=0;
};

class BCA : public virtual BS {
};

class BSS : public virtual BS {
};

class BCS : public virtual BCA, public virtual BSS {
};

class BI4 {
  public:
    void meth() {};
};

class BT4 : public virtual BI4, public virtual BSS {
};

class T4 : public virtual BCS, public virtual BT4 {
};

int main() {
  T4 t4;
};

现在的问题是虽然继承图中有void meth(),但这段代码无法编译:

$ g++ -c t.cc -std=c++11
t.cc: In function ‘int main()’:
t.cc:27:6: error: cannot declare variable ‘t4’ to be of abstract type ‘T4’
   T4 t4;
      ^
t.cc:23:7: note:   because the following virtual functions are pure within ‘T4’:
 class T4 : public virtual BCS, public virtual BT4 {
       ^
t.cc:3:18: note:        virtual void BS::meth()
     virtual void meth()=0;
                  ^
t.cc:3:18: note:        virtual void BS::meth()

在我看来好像BS某种方式看不到通过BS-> BCA-> BCS-> T4-> BT4-> BI4的过载meth()方法链。
但为什么?该方法显而易见,C ++使用的C3线性化算法应该能够非常清楚地找到它。

3 个答案:

答案 0 :(得分:5)

语言规则不允许。虚函数只能通过派生类中具有相同名称和参数的函数声明来覆盖。由于BI4不是来自BSBI4::meth无法覆盖BS::meth。如果某个类({1}}和BS继承(直接或间接),则它继承了名为BI4两个函数:一个来自meth,仍然是抽象的而不是被覆盖的,而且来自BS

答案 1 :(得分:2)

BI4不会直接或间接地从BS继承,因此其方法BI4::meth()完全不相关,无法覆盖BS::meth()

您只能覆盖基类中的方法,而不能覆盖“兄弟”或“叔叔”类中的方法。

答案 2 :(得分:2)

主要有两个方面:

  • 给定的类只能覆盖其基类中的成员函数 由于您的BI4类没有BS作为基类,因此无法覆盖BS中的任何内容。
  • 可以在虚拟基类中定义的纯虚函数的实现中继承,就像在Java中一样,但提供该实现的类本身也必须具有该虚基类。 / LI>

示例:

struct Base
{
    virtual void foo() = 0;
};

#ifdef GOOD
    struct Impl_foo: virtual Base
    {
        void foo() override {}
    };
#else
    struct Impl_foo
    {
        virtual void foo() {}
    };
#endif

struct Abstract_derived: virtual Base
{};

struct Derived
    : Abstract_derived
    , Impl_foo      // Java-like implementation inheritance.
                    // In C++ called "by dominance".
{};

auto main()
    -> int
{
    Derived o;
    o.foo();
}

如果没有定义GOOD宏符号,则此代码不会编译。