I. 問題の説明:
ClassDerived
は class の子ですBase
。クラスを変更することはできませんBase
。のコンストラクターと代入演算子を定義しDerived
て、次のインスタンスから両方を構築できるようにします。
Base
1Derived
1N
ポリモーフィックではなく、関連のない型Foo1
、...、FooN
2。
1両方からの構築は、Base
コピーコンストラクターDerived
を使用して行われます。Base
2Foo1
すべての, ...からの構築はFooN
、一般的なアルゴリズムによって行われます。
Ⅱ.可能な解決策:
1.ブルートフォース:
N+1
個別のコンストラクター +N+1
個別の代入演算子。絶対にエレガントではありません。大量の役に立たないコード:N+1
ヘッダーのメソッド宣言 +N+1
ソースのメソッド実装。テンプレートの力は使用されていません。
2.型制限のあるテンプレートコンストラクタ
通常のコピー コンストラクターを宣言して定義する
Derived::Derived ( const Base& object_reference ) { ... }
テンプレート コンストラクターを宣言します。
template<typename type>
Derived::Derived ( const type& object_reference );
Foo0
、...、のそれぞれに実装します。FooN
template<>
Derived::Derived<Foo0> ( const Foo0& object_reference ) { ... }
...
template<>
Derived::Derived<Foo9> ( const Foo9& object_reference ) { ... }
その結果、ヘッダーには 2 つのコンストラクターと 2 つの代入演算子のみが含まれます。N+1
ただし、ソースにメソッドを実装する必要があります。とにかくもっと良い解決策があると思います。
III. 動作しないもの:
1. dynamic_cast で Base と Derived を分離する
template<typename type>
Derived::Derived ( const type& object_reference )
{
// This line will not compile since `Foo0`, ... , `FooN` are non-polymorthic
Base* base_ptr = dynamic_cast <Base*> (&object_reference);
if ( base_ptr != nullptr )
{
// Construct from `Base`
return;
}
// Construct from `Foo0`, ... , `FooN`
}
2. typeid で Base と Derived を分ける
template<typename type>
Derived::Derived ( const type& object_reference )
{
if
(
typeid(typename) == typeid(Foo0)
||
...
||
typeid(typename) == typeid(FooN)
}
{
// Construct from `Foo0`, ... , `FooN`
return;
}
else
{
// Construct from `Base`
// Here we should call `Base` members which `Foo0`, ... , `FooN` don't have
// so the following line will not compile
// object_reference.some_method();
// And we need to cast "&object_reference" to "Base*" what is not possible
// because `Foo0`, ... , `FooN` are not polimorthic
}
}
IV. 質問:
問題を解決するために、セクション II で説明されていない効率的な方法はありますか?