13

クラスが相互に依存する非常に複雑なクラス階層があります。それぞれ C と A のインスタンスを返すメソッドを含む 2 つの抽象クラス A と C があります。継承されたクラスでは、共変型を使用したいと考えています。この場合、継承関係を前方宣言する方法がわからないため、これが問題になります。

"test.cpp:22: error: invalid covariant return type for 'virtual D* B::outC()'" エラーが発生します。これは、コンパイラが D が C のサブクラスであることを認識していないためです。

class C;

class A {
public:
        virtual C* outC() = 0;
};

class C {
public:
        virtual A* outA() = 0;
};


class D;

class B : public A {
public:
        D* outC();
};

class D : public C {
public:
        B* outA();
};

D* B::outC() {
        return new D();
}

B* D::outA() {
        return new B();
}

B::outC() の戻り値の型を C* に変更すると、例がコンパイルされます。継承されたクラスで B* と D* を戻り値の型として保持する方法はありますか (方法があることは直感的にわかります)。

4

3 に答える 3

8

私は、C++ で共変メンバーを直接結合する方法を知りません。レイヤーを追加するか、共変リターンを自分で実装する必要があります。

最初のオプションの場合

class C;

class A {
public:
        virtual C* outC() = 0;
};

class C {
public:
        virtual A* outA() = 0;
};


class BI : public A {
public:
};

class D : public C {
public:
        BI* outA();
};

class B: public BI {
public:
        D* outC();
};

D* B::outC() {
        return new D();
}

BI* D::outA() {
        return new B();
}

そして2番目に

class C;

class A {
public:
        C* outC() { return do_outC(); }
        virtual C* do_outC() = 0;
};

class C {
public:
        virtual A* outA() = 0;
};


class D;

class B : public A {
public:
        D* outC();
        virtual C* do_outC();
};

class D : public C {
public:
        B* outA();
};

D* B::outC() {
        return static_cast<D*>(do_outC());
}

C* B::do_outC() {
        return new D();
}

B* D::outA() {
        return new B();
}

この 2 番目のオプションは、コンパイラによって暗黙的に行われることに注意してください (static_cast が有効であるといういくつかの静的チェックを伴う)。

于 2010-03-09T16:38:23.383 に答える
4

私の知る限り、明示的なキャストなしでこれを行う方法はありません。問題は、 class の定義は、class の完全な定義を見るまで、それが のサブクラスであることを認識できBないが、 class の定義は、 classの完全な定義を見るまで、それが のサブクラスであることを認識できないことです。したがって、循環依存関係があります。残念ながら、前方宣言は継承関係を指定できないため、これは前方宣言では解決できません。DCDDBAB

clone()テンプレートを使用して共変法を実装しようとすると同様の問題があり、解決できることがわかりましたが、循環参照を解決できないため、同様の解決策はここでも失敗します。

于 2010-03-09T16:45:37.367 に答える
0

クライアント側の期待により、これを行うことはできません。C インスタンスを使用する場合、それがどの種類の C であるか (D かそれ以外か) はわかりません。したがって、B ポインター (派生クラスへの呼び出しの結果であるが、コンパイル時にそれがわからない) を A ポインターに格納すると、すべてのメモリ要素が正しくなるかどうかわかりません。

ポリモーフィック型でメソッドを呼び出す場合、ランタイム環境はオブジェクトの動的型をチェックする必要があり、クラス階層に合わせてポインターを移動します。共分散に頼るべきかどうかはわかりません。これを見てください

于 2010-03-09T16:31:52.837 に答える