2

I. 問題の説明:

ClassDerivedは class の子ですBase。クラスを変更することはできませんBase。のコンストラクターと代入演算子を定義しDerivedて、次のインスタンスから両方を構築できるようにします。

  • Base1

  • Derived1

  • Nポリモーフィックではなく、関連のない型Foo1、...、FooN2

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 で説明されていない効率的な方法はありますか?

4

3 に答える 3

1

コメントの情報から、実際には と の間に共通点がFoo1ありFooNます。つまり、それらはすべてソケット アドレスのエンコーディングです。そこで、さまざまなクラスでto_string()シリアライズを行い、FooAny

class FooAny // Any runs from 1 to N
{
public:
    std::string to_string() const { /* FooAny specific */ }
private:
    // bla
};

次に、そのデリゲートで単一のテンプレート コンストラクターを使用して、引数Derivedを取る通常のコンストラクターに渡します。std::string

class Derived
{
    explicit Derived(std::string const& s): /* convert data members from string */ {}

    template<class Foo>
    explicit Derived(Foo const& f): Derived(f.to_string()) {} // delegating constructor
};
于 2013-08-23T08:52:35.283 に答える