1

次のようなファクトリ パターンを実装しようとすると、同じ難問に何度も遭遇します。

class Base {
    template <typename T>
    void doSomethingWithMember(T){
    }
    void doing(){
        doSomethingWithMember(this->a);
    }
private:
    int a;      
};
class A: public Base {
    double a;
};
class B: public Base{
    float a;
};

struct Dictionary {
    typedef Base* (*FunctionPointer)(void);
    std::map <int, FunctionPointer> fmap;

    template <typename Target>
    static Base* construct() {
        return new Target();
    }

    Dictionary() {
        fmap.insert(std::make_pair(0, &Dictionary::construct<A>));
        fmap.insert(std::make_pair(1, &Dictionary::construct<B>));
    }

    Base* Call( int i ) const {
        std::map<int, FunctionPointer>::const_iterator entry = fmap.find( i );
        return entry == fmap.end() ? new Base() : (*entry->second)();
    }
};

問題は、最良の場合は非表示になるため、a定義できないことです。Baseしかし、i の定義がなけれaば、継承者が自分の に対処するための関数を実装できませんa。私が試したのはBase、辞書を介してオブジェクトを作成するときに返されるデータ型 (int、double、float) を常に知っておく必要があるという問題につながるテンプレートとして実装することでしBase<int>た。そして、他に何も知らずに に従ってオブジェクトを与えるには、辞書が必要です。Base<float>Base<double>ii

4

1 に答える 1

2

テンプレートを作成する際の問題Baseは、共通基盤を失ったことです。ただし、派生クラスをテンプレートにすることで、それを取り戻すことができます。例えば:

struct Base {
    virtual ~Base() { }
};
template<typename T>
struct Derived : Base {
private:
    T a;
};

Base *上記により、ファクトリ コンストラクトを持つ while を返すことができますDerived<X>。construct() 関数は次のようになります。

template<typename T>
static Base *construct() {
    return new Derived<T>();
}

操作が必要な関数はすべてaに配置されDerived<T>、 はテンプレートであるため、Derived一度実装するだけで済みます。

于 2013-05-15T16:49:03.433 に答える