あなたのデザインには不明なことはかなりありますが、質問があなたがそのタイプを強制できるかどうかである場合 T
メンバー関数テンプラ Add
導出することを強制することができます BaseClass
, 、オプションは簡単です:
- 何もしないでください、コンパイラは喜んでラインで文句を言います
BaseClass* baseClass = new T();
- これをより明確にするために、静的アサートを追加します
- 派手なsfinaeトリックを使用して、過負荷のセットから関数を削除します
私は最初の2つのいずれかに行きます。静的アサートは、次のように綴ることができます。
static_assert(std::is_base_of<BaseClass,T>::value);
sfinaeのトリック、私は本当にそれを避けるでしょう。それはコードをより混乱させるだろうからです。
template <class T>
typename std::enable_if<std::is_base_of<BaseClass,T>::value,T*>::type
Add() {
baseClasses.push_back(new T());
return baseClasses.back();
}
(返品タイプを変更したことに注意してください T*
, 、オブジェクトはaです T
, 、なぜ返すのか BaseClass*
?同じことが Get
関数aを返すことには意味がありません BaseClass*
, 、あなたがオブジェクトが本当に T
)
あなたの設計は所有権の考慮を積極的に避けているので、実際の問題ははるかに複雑です。オブジェクトの所有権について考え、明確な所有者(またはリソースが共有されていることを確認してください)を確認してください。誰がオブジェクトを所有しているかを知ったら、オブジェクトを削除する必要があるときに所有者に通知するために、コードの残りの部分のプロトコルを作成します。許可する場合 どれか 保持しているポインターを削除するためのコード、あなたはすぐに未定義の動作に遭遇するでしょう。
他のより少ない懸念には、すべてのコンポーネントがデフォルトのコンストラクターを持っていることを実施しているという事実が含まれます。非テンプレートを使用することにより、この制限を簡素化できます Add
それはポインターを取り、発信者に彼らが好きなようにオブジェクトを作成させることができます。
の用法 typeid
通常、コードスメルであり、これが例外ではないと思います。たぶん、オブジェクトが何であるかを実行するのではなく尋ねることができるタイプの階層を設計する方が良いでしょう。 typeid
. 。タイプに基づいてインターフェイスを作成することを本当に決心している場合は、 dynamic_cast
もっとよくなるはず。より無関係になりますが、複数のレベルの継承がある場合、中間オブジェクトとして最も派生オブジェクトを返すことができます