Baseから派生した100のクラスがあるとしましょう。これらの派生クラスのそれぞれには、コンパイル時に既知の[0,100)間の一意の識別子があります。
IDを受け取り、そのIDを持つ派生クラスの新しく割り当てられたインスタンスを返す必要がある関数があります。
Base* CreateDerived(uint32_t id) {
return new Derived...();
}
IDごとに巨大なスイッチケースを用意するのは明らかに良い解決策ではありません。私が思いつくことができる最良の解決策の例を以下に示しますが、vtableによって導入されるオーバーヘッドなしでこれを行う方法があるように感じます。
struct RegisteredClass {
static RegisteredClass* ClassTable[MAX_DERIVED_CLASSES];
static Base* CreateDerived(int ID) { return ClassTable[ID]->Create(); }
RegisteredClass(int ID) { ClassTable[ID] = this; }
virtual Base* Create() = 0;
};
template<typename T, int ID>
struct Register : RegisteredClass {
Register() : RegisteredClass(ID) { }
virtual Base* Create() { return new T; }
};
class Derived34 : Base {
static Register<Derived34, 34> _register;
};
私はばかげていますか、それともそれほど多くのスペースを必要としない別のアプローチがありますか?