1

I have this, maybe a little bit complex class hierarchy:

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;
};

Now the problem is that although the void meth() is available in the inheritance graph, despite this code won't compile:

$ 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()

It seems to me as if BS somehow wouldn't see the overloaded meth() method through the BS->BCA->BCS->T4->BT4->BI4 chain.
But why? The method is clearly available, the C3 linearization algorithm used by the C++ should be able very clearly find it.

4

3 回答 3

5

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

于 2016-07-06T18:33:25.970 回答
2

BI4BS直接或间接继承,因此它的方法BI4::meth()是完全不相关的,不能覆盖BS::meth().

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

于 2016-07-06T18:33:11.657 回答
2

主要有两个方面:

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

例子:

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宏符号,此代码将无法编译。

于 2016-07-06T18:45:27.130 回答