1

私はこれを持っていますが、おそらく少し複雑なクラス階層です:

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->BCA->BCS->T4->BT4->BI4 チェーンを介してBSオーバーロードされたメソッドが表示されないように思えます。 しかし、なぜ?メソッドは明らかに利用可能です.C++で使用されるC3線形化アルゴリズムは、それを非常に明確に見つけることができるはずです。meth()

4

3 に答える 3

2

主な側面は 2 つあります。

  • 特定のクラスは、その基本クラスのメンバー関数のみをオーバーライドできます。
    あなたのクラスは基本クラスとしてBI4持っていないので、から何かをオーバーライドすることはできません。BSBS
  • 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 に答える