6

同じ名前で異なる非共変の戻り型を持つ純粋仮想関数を定義する2つの抽象クラスがある場合、これらから派生して両方の関数の実装を定義するにはどうすればよいですか?

#include <iostream>

class ITestA {
    public:
        virtual ~ITestA() {};
        virtual float test() =0;
};

class ITestB {
    public:
        virtual ~ITestB() {};
        virtual bool test() =0;
};

class C : public ITestA, public ITestB {
    public:
    /* Somehow implement ITestA::test and ITestB::test */
};


int main() {
    ITestA *a = new C();
    std::cout << a->test() << std::endl; // should print a float, like "3.14"
    ITestB *b = dynamic_cast<ITestB *>(a);
    if (b) {
        std::cout << b->test() << std::endl; // should print "1" or "0"
    }
    delete(a);
    return 0;
}

C :: test()を直接呼び出さない限り、あいまいなものは何もないので、なんとか機能するはずだと思います。正しい表記がまだ見つからなかったと思います。または、もしそうなら、これは不可能ですか:なぜですか?

4

3 に答える 3

3

さて、それは可能です、そして方法はそれほど醜いものではありません。継承のレベルを追加する必要があります。

 ITestA       ITestB     <-- These are the interfaces C has to fulfill, both with test()
    |           |
ITestA_X     ITestB_X    <-- These classes implement the interface by calling a
    |           |             function with a different name, like ITestA_test
    \__________/              which is in turn pure virtual again.
         |
         C               <--  C implements the new interfaces

現在、Cには関数がありませんが、aをtest()にキャストする場合は、 inの実装が使用されます。にキャストする場合、からのdynamic_castでも、の実装が使用されます。次のプログラムは次のように出力します。3.140C*ITestA*test()ITestA_testITestB*ITestA*ITestB_test

#include <iostream>

class ITestA {
    public:
        virtual ~ITestA() {};
        virtual float test() =0;
};

class ITestB {
    public:
        virtual ~ITestB() {};
        virtual bool test() =0;
};

class ITestA_X : public ITestA {
    protected:
        virtual float ITestA_test() =0;
        virtual float test() {
            return ITestA_test();
        }
};

class ITestB_X : public ITestB {
    protected:
        virtual bool ITestB_test() =0;
        virtual bool test() {
            return ITestB_test();
        }
};

class C : public ITestA_X, public ITestB_X {
    private:
        virtual float ITestA_test() {
            return 3.14;
        }
        virtual bool ITestB_test() {
            return false;
        }
};

int main() {
    ITestA *a = new C();
    std::cout << a->test() << std::endl;
    ITestB *b = dynamic_cast<ITestB *>(a);
    if (b) {
        std::cout << b->test() << std::endl;
    }
    delete(a);
    return 0;
}

これにはあなたが考えることができる欠点がありますか?

于 2012-07-07T07:28:22.360 に答える
2

を宣言するITestA *a = new C()と、オブジェクトが作成されCます。testを使用して呼び出す場合は、仮想テーブルをa->test()使用して実行するコードを見つける必要があります。CしかしC、同じ署名の2つの異なる実装を作成しようとしていますがtest()、これは許可されていません。として宣言したという事実はITestA *、メソッドの解決には影響しません。メソッドを宣言したvirtualので、アクセスに使用したポインターのタイプに関係なく、オブジェクトの実際のタイプを介してメソッドが検出されます。

同じ名前と引数のタイプを持つ2つのメソッドを持つことはできません。このコードを構造化する別の方法を見つける必要があります。

于 2012-07-07T03:15:54.150 に答える
0

これは不可能だと思います。関数は名前(および署名)によってオーバーロードします。

于 2012-07-07T03:16:36.203 に答える