「More C++ Idioms/仮想コンストラクタ(Virtual Constructor)」の版間の差分
削除された内容 追加された内容
現内容を翻訳 |
|||
1 行
=<center>仮想コンストラクタ(Virtual Constructor)</center>=
===
あるオブジェクトのコピーか、新しいオブジェクトを、その具体的な型を知ることなしに生成する。
===
===
クラス階層中のメンバ関数の多態的な呼び出しを使うことは、オブジェクト指向プログラミングのコミュニティではよく知られたことである。
それは、'''is-a(~は~である)''' (より現実的には '''behaves-as-a(~として振る舞う)''')関係を実装する方法の一つである。
時々クラス階層中の生存期間管理(生成、コピー、破棄)関数を多態的に呼び出すことが便利な場合がある。
C++ は、仮想デストラクタを用いることでオブジェクトの多態的な破棄に(言語組み込みの機能で)対応している。
オブジェクトの生成やコピーに対しては同様の対応は存在しない。
C++ では、オブジェクトの生成には常にその型をコンパイル時に知っている必要がある。
仮想コンストラクタ(Virtual Constructor)イディオムは、C++ で多態的なオブジェクトの生成やコピーを可能とする。
===
以下のように、仮想コンストラクタの効果は、オブジェクトの生成に create() メンバ関数を用い、コピー生成に clone() メンバ関数を用いることで得られる。
<source lang="cpp">
class Employee
{
public:
virtual ~Employee () {} //
virtual Employee * create () const = 0; //
virtual Employee * clone () const = 0; //
};
class Manager : public Employee // "is-a"
{
public:
Manager (); //
Manager (Manager const &); //
~Manager () {} //
Manager * create () const //
{
return new Manager();
}
Manager * clone () const //
{
return new Manager (*this);
}
};
class Programmer : public Employee { /*
Employee * duplicate (Employee const & e)
{
return e.clone(); //
}
</source>
Manager クラスは 2 つの純粋仮想関数を実装し、型名(Manager)を用いてその型のオブジェクトを生成する。
duplicate 関数は、どのように仮想コンストラクタイディオムが使用されるかを示している。
duplicate 関数は、実際にはなにを複製しているかを知らない。
(実際には Manager かもしれないし Programmer かもしれない) Employee を複製していることを知っているだけである。
正しいインスタンスを生成する責任は派生クラスに委譲されている。
それゆえ、
Employee を頂点とするクラス階層に将来さらに派生クラスが追加されたとしても、duplicate 関数は変更に対して影響を受けない。
Manager クラスの clone および create メンバ関数の返値の型は Employee ではなく、そのクラス自身(Manager)である。
C++ は、オーバーライドした関数の返値の型を、基本クラス中での関数の返値の型の派生クラスの型にすることができるという自由度を認めている。
この言語機能は、'''共変の返値型(co-variant return types)'''として知られている。
リソースの所有権を正しく扱うため、clone() および create() 関数をファクトリ関数とみなし、その返値に対して、[[More C++ Idioms/リソースの返値(Resource Return)|リソースの返値(Resource Return)]]イディオムを用いるべきである。
使用した場合、返値の型は(例えば shared_ptr<Employee> と shared_ptr<Manager> のようになり)、もはや共変の返値型ではなくなりコンパイルに失敗するはずである。
そのような場合、派生クラスの仮想コンストラクタ関数は親クラスでの正確な型を返さなければならない。
<source lang="cpp">
55 ⟶ 70行目:
public:
typedef std::tr1::shared_ptr<Employee> Ptr;
virtual ~Employee () {} //
virtual Ptr create () const = 0; //
virtual Ptr clone () const = 0; //
};
class Manager : public Employee // "is-a"
{
public:
Manager () {} //
Manager (Manager const &) {} //
~Manager () {}
Ptr create () const //
{
return Ptr(new Manager());
}
Ptr clone () const //
{
return Ptr(new Manager (*this));
76 ⟶ 91行目:
</source>
===
===
* [[More C++ Idioms/リソースの返値(Resource Return)|リソースの返値(Resource Return)]]
=== References ===
* [http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8 Virtual Constructor]
[[Category:{{BASEPAGENAME}}|{{SUBPAGENAME}}]]▼
<noinclude>
[[en:More C++ Idioms/Virtual Constructor]]
</noinclude>
|