1

A、B、C という名前の 3 つのクラスがあります。B は A から継承し、C は B から継承します (A -> B -> C)。

IBinary という名前の抽象基本クラスもあります。すべてのクラスで IBinary インターフェイスを実装したいと考えています。クラス A を IBinary から継承させると、コードの出力はC::readb. クラス A が IBinary を継承しない場合、出力はB:readb.

3 つのクラスを同じインターフェイスにサブスクライブさせる適切な方法は何ですか? トップ クラス (A) のみがインターフェイス クラスから継承されている場合、上記のような解決の問題が発生しないように、コードをリファクタリングする必要があります。

すべてのクラスをインターフェイス クラスから明示的に継承させると、クラス階層がより複雑になり、ダイアモンド オブ ダイアモンドに近づきます。


#include <iostream>

class IBinary {
public:
    virtual void readb( std::istream& in ) = 0;
};

// Basic A -- change whether this inherits from IBinary
class A : public IBinary {
public:
    A() {};

    void readb( std::istream& in ) {}
};

// Specialized A
class B : public A {
public:
    B() {};

    void load() {
        this->readb(std::cin);        // <-- which readb is called?
    }
    void readb( std::istream& in ) {
        std::cout << "B::readb" << std::endl;
    }
};

// Specialized B
class C : public B {
public:
    C() {};

    void readb( std::istream& in ) {
        std::cout << "C::readb" << std::endl;
    }
    void foo() {
        B::load();
    }
};

int main() {
    C c;
    c.foo();
}
4

3 に答える 3

1

virtual定義でIBinary::readbは、すべての違いが生じます。

から継承すると、階層内の からの をオーバーライドするIBinaryすべてのも暗黙的に仮想になります。したがって、想定どおりに、仮想距離が開始されます。readbIBinary

そうしないと、呼び出しは静的に解決されます。呼び出しは 内Bにあるため、呼び出されるのはB::readbです。

于 2013-08-01T19:17:23.950 に答える
1

この動作が見られる理由は、要するに、A::readbが宣言されていないためですvirtual

IBinary::readbisvirtualであるためA、それを継承すると、デフォルトで にA::readbなりvirtualます。

の最初の宣言だけでなく、virtualすべての宣言に,を追加すると、コードの動作がより一貫したものになります。readbこのため、C++ の多くのコード スタイル ガイドでは、すべての派生クラスですべてのvirtualメソッドを宣言する必要がありvirtualます (それらが祖先の基本クラスではない場合でも)。

于 2013-08-01T19:16:21.727 に答える