ポリモーフィズムで実体も取っておく

備忘録。

container<CObject*> box;

CObject *object = new CObject(a,b,c);
box.push_back( object );

良くあるポリモーフィズム
CObjectを継承したCRenderObjectを入れたいなら

CRenderObject *robject = new CRenderObject(a,b,c);
box.push_back( robject  );

だが、後々になってコンテナboxにあるCRenderObjectの独自関数を呼びたいケースが多々ある。これは幾つかの実装方法がある。

CRenderObject robject =
	dynamic_cast<CRenderObject>(box.back());

これは危険だ。box.back()がCRenderObjectであるとは限らないし、その保証があるならそもそも挿入時に予めよけておくべきである。

CRenderObject *robject = new CRenderObject(a,b,c);
Archive->renderobject = robject;
box.push_back( robject  );

あとはArchive君が持っているものを呼び出せばいい。

さて、小規模なモノならこれで十分だが、恐らくあなたは次にこのObjectをもっと便利に追加したくなるだろう。
例えば、objectの中にもboxがあって、その中にobjectを入れたい時などだ。

box[0].addChild(a,b,c);

addChildの中身はこうなる。

void CObject::addChild(int a,int b,int c)
{
	CObject *object = new CObject(a,b,c);
	this->box.push_back( object );
}

newを内部に隠蔽できるので、removeChildでdeleteも隠蔽してしまえばあなたはわずらわしいメモリ管理から解放される。
おっと。この場合、派生オブジェクトはどうやって確保すればいいんだろうか。dynamic_castは禁じ手だ。
正解は、templateのごく標準的な使い方で事足りる。

template<typename T>
T* CObject::addChild(int a,int b,int c)
{
	T *object = new T(a,b,c);
	this->box.push_back( object );
	return object;
}

で、宣言はこうなる。

Archive->renderobject =
	box[0].addChild<CRenderObject>(a,b,c);

これで万事解決。