共通ベース から派生した一連のオブジェクトがありますApiObject
。すべての ApiObjects を個別のデータ構造に登録できる必要がありますが、基本クラスではなく、作成されるオブジェクトの実際のアドレスが必要です (多重継承を使用しています)。
ApiObject
派生オブジェクトのアドレスがわからないため、コンストラクターにオブジェクトを登録するコードを配置できません。また、派生クラスのコンストラクターに入れることもできません。別の派生クラスを実際に構築しているかどうかを知る方法がないためです (たとえば、 classB
が から継承されA
、両方を構築できる場合)。
したがって、私が見る唯一のオプションは、次のように、オブジェクトを作成するたびに登録関数を明示的に呼び出すことです。
B* b = new B(...);
RegisterObject(b);
ただし、毎回この関数を呼び出すことを覚えておく必要があるため、これはあまり良い解決策ではないようです。
なぜこれを行っているのかを説明するために、より多くのコンテキストを提供する必要があると思います。オブジェクトはオーバーロードされた new 演算子を介して作成され、オブジェクトが作成されたコンテキスト (Lua 状態) を知る必要があります。例えば
Foo* object = new(L) Foo(...);
// Foo is derived from ApiObject, and we want ApiObject to have a reference to L
現在、それはやや洗練されていない方法で行われています - new 演算子は、オブジェクトの前に追加のバイトを割り当て、そこに L ポインターを格納し、オブジェクトの型を記述するための追加データをいくつか追加します。次に、基本クラスは init 関数を介してこの「メタデータ」へのポインターを受け取ります。
それ以外の場合、最初に頭に浮かぶのは仮想関数ですが、コンストラクターから呼び出すことはできないため、ベースApiObject
ポインターを登録する必要がありますが、後で仮想関数を呼び出すだけです。それは私の現在の実装よりもきれいです。