C++言語には、直接的な意味での「バーチャルコンストラクタ」という概念は存在しませんが、実行時にのみ知られる型に基づいて派生クラスのオブジェクトのインスタンスを作成する必要があることはよくあります。このような課題は、通常、仮想関数(通常は「clone()」または「create()」)を通じて「バーチャルコンストラクタ」パターンで解決されます。
問題の歴史: C++の初期バージョンから、制限に直面しました:コンストラクタをバーチャルとして宣言することはできません。しかし、時折、クラス階層の中で、既存のものに基づいて新しいオブジェクトを作成する必要があります(または型を実行時にのみ完全に知っている場合)。
問題: 古典的には、コンストラクタはバーチャル関数のメカニズムに従いません — 呼び出しは常にコンパイル時に解決されます。これにより、基底クラスのコンストラクタを介して実際の実行時型を持つ生成オブジェクトの「ライブ」ファクトリーを作成することができません。
解決策: 基底クラスに仮想関数を実装することが推奨されます — 通常はclone()(オブジェクトのコピーを作成)またはcreate()(状態をコピーせずに同じ型のオブジェクトを作成)です。
コード例:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { public: Derived(int v) : value(v) {} Base* clone() const override { return new Derived(*this); } private: int value; }; void process(const Base& b) { Base* b2 = b.clone(); // 仮想メソッドを介して正しいコピーを作成 delete b2; }
主な特徴:
C++でコンストラクタをvirtualとして宣言できますか?
いいえ、C++の構文ではコンストラクタにvirtual修飾子を使用することはできません。そうでなければ、コンパイラはコンパイルエラーを発生させます。
clone()を自分で宣言する場合、基底クラスでpure virtualにする必要がありますか?
いいえ、必ずしもそうではありません。状態の一部のみをコピーする、またはnullptrを返すという意味でclone()にデフォルト実装を与えることができますが、通常はより大きな制御のために純粋仮想関数(pure virtual)として行います。
ファクトリの静的メソッドをclone()の代替として使用できますか?それはバーチャリティとどのように関連していますか?
静的ファクトリーメソッドはバーチャルではなく、古典的なメカニズムによって派生クラスでオーバーライドされることはありません。真の「バーチャルコンストラクタ」には、インスタンスの仮想関数または型の動的解決の別の方法が必要です。
開発者は静的メソッドを介してパターンを実装しました:
class Base { public: static Base* create() { return new Base; } }; class Derived : public Base {}; // ... Base::create()が呼び出され、Baseを返し、実際の型の情報が失われる
利点:
欠点:
コードはclone()を使用します:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { int x; public: Derived(int x) : x(x) {} Base* clone() const override { return new Derived(*this); } };
利点:
欠点: