質問: 0; t(){ } }; class tA : public t { private: public: virtual tA* f()const { cout << "tA\n"; return new tA; } tA(){ } }; class tB : public t { public: virtual t* f()const { cout << "tb\n"; return new tB; } tB() { } }; ```
回答: C++言語での該当仕様を理解するには、前提条件としてクラス間の派生(derived)関係と、メンバ関数オーバーライド(override)の基本ルールを把握しておく必要があります。 C++においては「関数オーバーライド時に戻り値型・各引数の型を変更してはいけない」という基本ルールがあります。 ``` class Base { virtual int mf() { /*...*/ } }; class Derived : public Base { // NG: コンパイルエラー! // 派生クラスでの関数mfオーバーライド時に戻り値型を // int → double へと変更しようとしている。 virtual double mf() { /*...*/ } }; ``` このルールの**特例措置**として、該当参考書が説明する 共変(*covariant*) という概念が登場します。 ``` class Base { virtual Base* clone() { /*...*/ } }; class Derived : public Base { // OK: // 関数cloneオーバーライド時に戻り値型を // Base* → Derived* へと変更している。 // この戻り値型変更だけは特別に許可されている。 virtual Derived* clone() { /*...*/ } }; ``` この特別ルールのユースケースとして、上記例示コードのようなオブジェクト複製(clone)操作がよく取り上げられます。つまり基底クラス`Base`の複製操作では`Base`型を返し、派生クラス`Derived`の複製操作では`Derived`型を返したいという使い方です。