答えは質問にあるようです-あなたが提案した方法は正しい方向にあるようですが、それらの共有メンバーが多数ある場合は、それらを構造体またはクラスに集めて、それを過ぎて次のようにします。基本クラスのコンストラクタへの引数。
「共有」メンバーを派生クラスの静的メンバーとして実装することを主張する場合は、派生クラスのコードを自動生成できる場合があります。XSLT は、単純なクラスを自動生成するための優れたツールです。
一般に、この例では「仮想静的」メンバーの必要性は示されていません。このような目的では、継承は実際には必要ないためです。代わりに、基本クラスを使用して、コンストラクターで適切な値を受け入れさせる必要があります。各「サブタイプ」の引数の単一のインスタンスを作成し、共有データの重複を避けるためにポインターを渡します。別の同様のアプローチは、テンプレートを使用し、関連するすべての値を提供するクラスをテンプレート引数として渡すことです (これは一般に「ポリシー」パターンと呼ばれます)。
結論として、元の例では、そのような「仮想静的」メンバーは必要ありません。あなたが書いているコードにそれらがまだ必要であると思われる場合は、詳しく説明し、より多くのコンテキストを追加してみてください。
上記で説明した例:
class BaseClass {
public:
BaseClass(const Descriptor& desc) : _desc(desc) {}
string GetName() const { return _desc.name; }
int GetId() const { return _desc.Id; }
X GetX() connst { return _desc.X; }
virtual void UseClass() = 0;
private:
const Descriptor _desc;
};
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(Descriptor("abc", 1,...)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass("Wowzer", 843,...) {}
virtual void UseClass() { /* do something */ }
};
この解決策について詳しく説明し、初期化解除の問題の解決策を提供したいと思います。
少し変更するだけで、派生クラスのインスタンスごとに「記述子」の新しいインスタンスを必ずしも作成しなくても、上記の設計を実装できます。
各記述子の単一のインスタンスを保持するシングルトン オブジェクト DescriptorMap を作成し、次のように派生オブジェクトを構築するときにそれを使用できます。
enum InstanceType {
Yellow,
Big,
BananaHammoc
}
class DescriptorsMap{
public:
static Descriptor* GetDescriptor(InstanceType type) {
if ( _instance.Get() == null) {
_instance.reset(new DescriptorsMap());
}
return _instance.Get()-> _descriptors[type];
}
private:
DescriptorsMap() {
descriptors[Yellow] = new Descriptor("Yellow", 42, ...);
descriptors[Big] = new Descriptor("InJapan", 17, ...)
...
}
~DescriptorsMap() {
/*Delete all the descriptors from the map*/
}
static autoptr<DescriptorsMap> _instance;
map<InstanceType, Descriptor*> _descriptors;
}
これで、次のことができます。
class DerivedClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.BananaHammoc)) {}
virtual void UseClass() { /* do something */ }
};
class DerDerClass : public BaseClass {
public:
DerivedClass() : BaseClass(DescriptorsMap.GetDescriptor(InstanceType.Yellow)) {}
virtual void UseClass() { /* do something */ }
};
実行の最後に、C ランタイムが非初期化を実行するときに、autoptr を含む静的オブジェクトのデストラクタも呼び出します。これにより、DescriptorsMap のインスタンスが削除されます。
これで、実行終了時に削除される各記述子のインスタンスが 1 つになりました。
派生クラスの唯一の目的が関連する「記述子」データを提供することである場合 (つまり、仮想関数を実装するのではなく)、基本クラスを非抽象化し、適切なインスタンスを作成するだけで間に合わせる必要があることに注意してください。毎回記述子。