"virtual constructor idiom"は、プライベートまたは保護コピーコンストラクタが必要な重要なケースです。 C++では、基本クラス、この基本クラスから実際に継承されたオブジェクトのポインタを与えられ、そのコピーを作成する必要があります。コピーコンストラクタを呼び出すと、継承クラスのコピーコンストラクタは呼び出されませんでしたが、実際にはベースクラスのコピーコンストラクタが呼び出されます。
は守ってください。
class Base {
public:
Base(const Base & ref){ std::cout << "Base copy constructor" ; }
};
class Derived : public Base {
public:
Derived(const Derived & ref) : Base(ref) { std::cout << "Derived copy constructor"; }
}
Base * obj = new Derived;
Base * obj2 = new Derived(*obj);
上記のコードは出力を生成します:
"Base copy constructor"
これは明らかにプログラマが望んでいた動作ではありません!プログラマは "Derived"型のオブジェクトをコピーしようとしましたが、代わりに "Base"型のオブジェクトを戻しました!!
上記のイディオムを使用して問題を修正します。すなわち
"Base copy constructor"
"Derived copy constructor"
、所望のタイプの中で構築された」オブジェクト:上記のコードは出力を生成する
class Base {
public:
virtual Base * clone() const = 0; //this will need to be implemented by derived class
protected:
Base(const Base & ref){ std::cout << "Base copy constructor" ; }
};
class Derived : public Base {
public:
virtual Base * clone() const {
//call private copy constructor of class "Derived"
return static_cast<Base *>(new Derived(*this));
}
//private copy constructor:
private:
Derived(const Derived & ref) : Base(ref) { std::cout << "Derived copy constructor"; }
}
Base * obj = new Derived;
Base * obj2 = obj->clone();
:上記の記述された例を観察し、このイディオムを使用するように書き換え「派生型」であり、「ベース」型ではありません。
派生型では、巧妙なインターフェイスを使用するのではなく、誤ってコピーコンストラクターを手動で呼び出すことができないようにするために、APIの設計が間違っているため、コピーコンストラクターを意図的にプライベートにしましたclone()によって提供されます。別の言い方をすれば、直接呼び出し可能なパブリックコピーコンストラクタを使用すると、パート1で説明した間違いをプログラマに引き起こす可能性があります。この場合、コピーコンストラクタを表示から非表示にし、 "clone( )」。
割り当てコンストラクタのようなものはありません、移動コンストラクタを意味するのですか? – Praetorian
それはtypoだった...今それを修正しました...代入演算子 –
彼は主な理由私はその質問を尋ねています私はC++の本を読んでいて、C++をすべて自分で学習しています...そして私が読んでいる本 Lippman 、Lajoie C++ PrimerとStroustrupなどは、このようなアプローチが必要とされる現実の例を十分には与えていません。 もちろん、徹底的なリストを提供することはできません... しかし、そのようなアプローチが有用ないくつかのケース(例:@tcによる車の例のように) と私はすでに述べていますポインタまたはファイルのような一意のオブジェクトとの関連付け....... –