2012-02-28 5 views
1

複数の継承で、基本クラスの仮想関数の1つが単一の仮想定義になることを指定する方法があるかどうかを知りたい。私がこれを行う方法は、派生クラスにこの関数の明示的な定義を記述し、明示的に基本クラスの1つを呼び出すことです。これは厄介で、私はusingが助けてくれることを願っていましたが、そうではありません。多重継承は、それを再分割せずに所望の仮想関数を指定する

例えば、私はちょうどクラスBのバージョンに転送したいのに、私はC::valueを定義する必要があります。もっと簡単な方法はありませんか?

#include <iostream> 

using namespace std; 

struct A 
{ 
    virtual char const * value() const 
    { return "A"; } 
}; 

struct B 
{ 
    virtual char const * value() const 
    { return "B"; } 
}; 

class C : public A, public B 
{ 
public: 
    //using B::value; 
    virtual char const * value() const 
    { return B::value(); } 
}; 

int main() 
{ 
    C obj; 
    cout << obj.value() << endl; 

    A * ptr = &obj; 
    cout << ptr->value() << endl; 
} 

いくつかの注意:クラスAのこの特定のケース仮想継承で

  • は、クラスBのためのオプションではありません - 私は理論的構造体でベース
  • まで適切な建設チェーンを必要としますBはAとは無関係に使用することもできますが、他のオプションを提供する場合はそうではありません。
  • valueは何らかの理由で役立つ場合は純粋仮想としてマークされていますが、それは信じられません。

私は疑う「B」になる必要がありますAから派生したが

  • 明確にするために、しかし「FUNC」あらゆるタイプのポインタを通じて、Cで呼び出されたBではない他のクラスがあり、答えは "いいえ"かもしれませんが、いくつかの確認は良いでしょう。言語がこのパターンをサポートしなければならないように感じます。

  • +0

    上記のプログラムの出力は何ですか? – Bingo

    +0

    継承ツリーにダミーの「ノード」を追加することもできます(例えば、「A」から仮想的に継承する「DummyC」、「DummyC」および「B」から継承する「C」)。それが可能かどうかはわかりませんが、こちらをご覧ください:http://stackoverflow.com/questions/3310910/method-resolution-order-in-cこれが役立つかどうかを確認してください。 – Asaf

    +0

    @Bingo、私は関数をオーバーライドするので、上記のプログラムは "B"と "B"を出力します。あなたがこれをしないならば、単に 'using'宣言をして" B "と" A "を得るでしょう。 –

    答えて

    2

    私はこれを行うには見る唯一の方法は、派生クラスで の明示的な定義に、この関数を書くことである...、と私はあなたの中かもしれない ヘルプ

    usingキーワードを使用して期待していましたコンテキストはにのみ使用され、現在のスコープ(名前隠蔽に対して使用される)に名前が持ち込まれます。あなたの要求された機能が既に存在すると仮定してください。さて、以下の修正コードを参照してください。

    struct A 
    { 
        virtual char const * value() const 
        { return "A"; } 
    
        void value (double); // new function 
    }; 
    
    class C : public A, public B 
    { 
    public: 
        using B::value; 
        void value(int); // new function 
    }; 
    

    たちはACvalue(int)value(double)と同じ名前の機能を持っていると仮定します。これらの2つの関数はvirtual value()とは無関係で、オブジェクトはCで使用されます。

    どのようにA::value(double)Cのオブジェクトに使用しますか?当然あなたはCの体でusing A::value;をしなければなりません。今これのために、副作用として私達は2 virtual機能一致を持っています:A::value() constおよびB::value() const
    A*またはB*と呼ばれるときに選択するのはどちらですか?

    これはほんの一例ですが、その他の問題もあります。あなたの質問で言及したことは、正しい結果を達成するための最良の方法です。 C::value() constは、B::value() constのラッパーです。

    -1

    複数の継承は非常に稀であり、そのような関数を書くのは些細なので、言語機能に値するものではなく、そのような機能を提供するものはありません。

    唯一の影響は可視性ですが、これは問題ではないため、ほとんどの場合、何の助けにもなりません。

    +0

    あなたのメモが正しいとはいえ、私は多重継承はまれだとは考えていません。実際、このパターンがサポートされていれば、より一般的かもしれません。さらに、PythonやRubyのような言語はそのようなことを行うことができるので、「それほど価値がない」として完全に割り引くことはできません。 –

    +0

    @ edA-qamort-ora-y:どうしてですか?それらの他の言語はまったく無関係です。 「価値がある」とは、「C++標準委員会の意見ではC++の価値がある」ということです。 RubyやPythonはどこに記載されていますか?どこにもない。 MIは賢明にはほとんどのプログラマによって回避されており、これはMIが抱えている他の問題の海と単純なフォワーディング機能を単純に定義する簡単な解決法に比べれば、非常に小さいドロップです。 – Puppy

    +0

    IME、mixinはまれですが_far_です。 – ildjarn

    0

    いいえバイナリスコープ解決operator::を使用して、関数を明示的に呼び出す以外に他の方法はありません。

    -1

    インターフェイスメソッドを非仮想として使用する方が常に良いです。以下のコードは、あなたが望むものを習得するのに役立ちます。しかし、出力は異なります。私はそれがすべきことだと信じています。
    コードを見つけることができますhere

    出力:

    B

    #include <iostream> 
    
    using namespace std; 
    
    struct A 
    { 
        char const* value() const 
        { 
         return valueImpl(); 
        } 
    protected: 
        virtual char const * valueImpl() const 
        { return "A"; } 
    }; 
    
    struct B 
    { 
        char const* value() const 
        { 
         return valueImpl(); 
        } 
    protected: 
        virtual char const * valueImpl() const 
        { return "B"; } 
    }; 
    
    class C : public A, public B 
    { 
    public: 
        using B::value; 
    
    }; 
    
    int main() 
    { 
        C obj; 
        cout << obj.value() << endl; 
    
        A * ptr = &obj; 
        cout << ptr->value() << endl; 
    } 
    
    +0

    出力 "B" "A"、 "B" "B"が必要な場合、結果オブジェクトに対して定義され、アクセス可能な 'value()'が1つだけ存在する必要があります。 –