9

おそらく、関数名とパラメーターは同じですが、戻り値が異なる2つのインターフェイスがあります。

struct A { virtual void foo() = 0; };
struct B { virtual int foo() = 0; };

このインターフェイスを継承するクラス C を定義する方法 (もちろん可能であれば)? たとえば、コンパイルされない擬似コードをいくつか書きます。

// this code is fake, it doesn't compiled!!
struct C : A, B
{
    // how to tell compiler what method using if referenced from C?
    using void foo();  // incorrect in VS 2012
    // and override A::foo() and B::foo()?
    virtual void foo() { std::cout << "void C::foo();\n"; } // incorrect
    virtual int foo() { std::cout << "int C::foo();\n"; return 0; } // incorrect
 }
 // ... for use in code
 C c;
 A &a = c;
 B &b = c;
 c.foo();     // call void C::foo() when reference from C instance
 a.foo();     // call void C::foo() when reference from A instance
 b.foo();     // call int C::foo() when reference from B instance
4

4 に答える 4

4

それは不可能ですが、多重継承のためではありません。fooin classの無効なオーバーロードにより、あいまいさが生じCます。戻り値の型は関数シグネチャの一部ではないため、両方int foo()を持つことはできません。したがって、コンパイラは への呼び出しを解決できません。インターフェイスをとクラスの両方の結合として見ることができるため、論理的には、実際の継承の前に問題がすでに存在しています。コンパイラの観点からすると、 とは 2 つの別個の無関係な型であるため、それらをコンパイルしても問題はなく、エラーは class で実際に統合されるまで遅延します。void foo()fooABABC

関数シグネチャとオーバーロードの詳細については、こちらを参照してください: Is the return type part of the function signature?

于 2012-11-19T22:10:34.480 に答える
2

あなたができることは、すべての共有されたものをvirtualベースに入れ、補助クラスC_baseの競合する関数をそれぞれオーバーライドすることです。virtualで共有されているものCはすぐに利用できるため、C_base基本的に最も派生しCた . 最後に、Cクラスが物事をまとめるという理由だけでクラスを作成します。

struct A { virtual void foo() = 0; };
struct B { virtual int foo() = 0; };

struct C_base { int all_data; };

struct A_aux: virtual C_base, A {
    void foo() { std::cout << "A_aux::foo()\n"; }
};

struct B_aux: virtual C_base, B {
    int foo() { std::cout << "B_aux::foo()\n"; return 0; }
};

struct C : A_aux, B_aux
{
    using A_aux::foo;
};
于 2012-11-19T22:24:46.490 に答える
2

明示的に資格を得ることができます。

class C : A, B {
public:
    void A::foo() { ... }
    int B::foo() { ... }
};

編集:

これは、標準ではなく MSVC 拡張機能のようです。

于 2012-11-19T22:26:39.457 に答える
1

同じシグネチャを使用して仮想関数の戻り値の型を上書きすることはできません (@icepack の回答で説明されているように)。

別の方法として、テンプレートの基本クラスでテンプレート パラメーターとして指定された戻り値の型を宣言foo()し、具体的な戻り値のパラメーター型の特殊化を提供することもできます。

これは、@Dietmar Kühl の提案の一般化です。

于 2012-11-19T22:23:39.003 に答える