7
class messageA {
};

class messageB {
};

template<class T>
class queue {
public:
    virtual ~queue() {}
    void submit(T& x) {}
};

class A : public queue<messageA>, public queue<messageB>
{
};

int main()
{
    A aa;
    aa.submit(messageA());
    aa.submit(messageB());
}

私の最初の考えは、クラス A には messageA と messageB オブジェクトを受け入れる 2 つのオーバーロードされた送信関数が含まれているため、上記のコードは問題ないはずです。

ただし、コンパイラは次のエラーを表示します。

あいまいな理由がわかりますか?最初のサブミット呼び出しで、messageA バージョンを呼び出したいのは明らかではありませんか? 2 回目の送信呼び出しでは、messageB バージョンを呼び出したいですか?


------ Build started: Project: main, Configuration: Release Win32 ------
Compiling...
main.cpp
.\main.cpp(21) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(21) : error C3861: 'submit': identifier not found
.\main.cpp(22) : error C2385: ambiguous access of 'submit'
        could be the 'submit' in base 'queue<messageA>'
        or could be the 'submit' in base 'queue<messageB>'
.\main.cpp(22) : error C2664: 'queue<T>::submit' : cannot convert parameter 1 from 'messageB' to 'messageA &'
        with
        [
            T=messageA
        ]
.\main.cpp(22) : error C3861: 'submit': identifier not found
4

2 に答える 2

12

私は現在コンパイラを持っていませんが、1 つの継承が他の継承を隠す可能性があると思います: コンパイラはKoenig Lookupを使用して適切なシンボルを見つけます。 ")、親および/または外部スコープでの他の検索を停止します。

この場合、両方の継承クラスでシンボルが検索されると思いましたが、正確なコンパイラ (Visual C++ 2003 ? 2008 ? 2010 ?) がなければ、それ以上推測できません。

いくつかの考えの後、別の可能性として、コンパイラーが両方のシンボルを見つけたが、どちらを呼び出すかを決定できなかった可能性があります (シンボル解決のその時点で、コンパイラーは正確なプロトタイプではなく、シンボル名のみを考慮します)。この最後の説明が正しいと思います。

派生クラスに using ステートメントを追加してみてください。

class A : public queue<messageA>, public queue<messageB>
{
   using queue<messageA>::submit ;
   using queue<messageB>::submit ;
} ;

両方の送信メソッドを直接 A クラス スコープに移動します。

また、サブミット メソッドはメッセージを非 const 参照として受け取っているのに対し、コンストラクターではメッセージ パラメーターは一時的 (したがって、const r-values) であることに注意してください。

メインを次のように書き換えます。

int main()
{
    A aa;
    messageA mA ;
    messageA mB ;
    aa.submit(mA);
    aa.submit(mB);
}

コンパイルに役立つ可能性があります(これにより、22行目のコンパイラエラーが説明される可能性があります)。

または、submit メソッドのプロトタイプを変更して、非 const 参照ではなく const 参照を受け入れるようにすることもできます。

注: まだコンパイラがないので、コードを頭脳デバッグしようとしています... :-P ...

于 2010-07-29T09:10:05.910 に答える
1
Something* smth1 = ((Base<Something> *)d)->createBase<Something>();

上記のコードは正常に動作します。

于 2012-06-29T09:05:22.433 に答える