2013-05-06 69 views
0

我正在使用C++ 98。我想创建一个基于模板的通用工厂,创建者可以不带参数来创建目标对象或一个参数。如何创建基于通用模板的工厂?

/*<class.h> begins 

#ifndef INCLUDED_CLASS 
#define INCLUDED_CLASS 

#include <iostream> 
#include <boost/shared_ptr.hpp> 

class A 
{ 
public: 
    A() { _a = 27; } 
    void print() const { std::cout << "A is " << _a << "." << std::endl; } 
protected: 
    int _a; 
}; 
typedef boost::shared_ptr<A> APtr; 

class AA : public A 
{ 
public: 
    void print() const { std::cout << "AA is " << _a << "!" << std::endl; } 
}; 

class B 
{ 
public: 
    B(double b) { _b = b; } 
    void print() const { std::cout << "B is " << _b << "." << std::endl; } 
protected: 
    double _b; 
}; 
typedef boost::shared_ptr<B> BPtr; 

class BB : public B 
{ 
public: 
    BB(double b) : B(b) {}; 
    void print() const { std::cout << "BB is " << _b << "!" << std::endl; } 
}; 

#endif 

/*<class.h> ends 



/*<factory.h> begins 

#ifndef INCLUDED_FACTORY 
#define INCLUDED_FACTORY 

#include <map> 
#include <string> 
#include <boost/shared_ptr.hpp> 

template<class bT, class pT=void> 
class Creator 
{ 
public: 
    virtual bT* create() = 0; 
    virtual bT* create(const pT* param) = 0; 
}; 

template <class bT, class pT> 
struct CreatorPtr 
{ 
    typedef boost::shared_ptr< Creator<bT> > type; 
}; 


template <class bT, class cT, class pT> 
class CreatorImpl : public Creator<bT, pT> 
{ 
public: 
    virtual bT* create() { return new cT; } 
    virtual bT* create(const pT* param) { return new cT(param); } 
}; 


template<class bT, class pT=void> 
class Factory 
{ 
public: 
    virtual bT* create(const std::string& name) const = 0; 
    virtual bT* create(const std::string& name, const pT* param) const = 0; 
protected: 
    Factory() {} 
    Factory(const Factory&) {} 
    Factory &operator=(const Factory&) { return *this; } 
    void registerCreator(const std::string& name, typename CreatorPtr<bT, pT>::type creator) 
     { _table_creator[name] = creator; } 
    typedef std::map<std::string, typename CreatorPtr<bT, pT>::type> tableCreator; 
    typedef typename tableCreator::const_iterator citerTc; 
    citerTc begin() const { return _table_creator.begin(); } 
    citerTc end() const { return _table_creator.end(); } 
    citerTc find(const std::string& name) const { return _table_creator.find(name); } 
protected: 
    tableCreator _table_creator; 
}; 

class A; 
class EngineA : public Factory<A> 
{ 
public: 
    virtual A* create(const std::string& name) const 
    { 
     citerTc it = find(name); 
     if (it != end() && it->second) 
     { 
      return it->second->create(); 
     } 
     else 
      return (A*)NULL; 
    } 

    static Factory<A>& get() 
    { 
     static EngineA instance; 
     instance.registerEngine(); 
     return instance; 
    } 
private: 
    virtual A* create(const std::string& name, const void* param) const { return (A*)NULL; } 
private: 
    virtual void registerEngine(); 
}; 

void EngineA::registerEngine() 
{ 
    CreatorPtr<A, void>::type AACreator(new CreatorImpl<A, AA, void>); 
    registerCreator("AA", AACreator); 
} 

class B; 
class EngineB : public Factory<B, double> 
{ 
public: 
    virtual B* create(const std::string& name, const double* value) const 
    { 
     citerTc it = find(name); 
     if (it != end() && it->second && value) 
     { 
      return it->second->create(value); 
     } 
     else 
      return (B*)NULL; 
    } 

      static Factory<B, double>& get() 
    { 
     static EngineB instance; 
     instance.registerEngine(); 
     return instance; 
    } 
private: 
    virtual B* create(const std::string& name) const { return (B*)NULL; } 
private: 
    virtual void registerEngine(); 
}; 

void EngineB::registerEngine() 
{ 
    CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>); 
    registerCreator("BB", BBCreator); 
} 

#endif 

/*<factory.h> ends 



/*<main.cpp> begins 

#include <class.h> 
#include <factory.h> 

int main(void) 
{ 
    APtr a(EngineA::get().create("AA")); 
    if (a) 
     a->print(); 

    double value = 35.7; 
    BPtr b(EngineB::get().create("BB",&value)); 
    if (b) 
     b->print(); 

    return 0; 
} 

/*<main.cpp> ends 

的编译错误是:

....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp: In constructor ‘boost::shared_ptr<T>::shared_ptr(Y*) [with Y = CreatorImpl<B, BB, double>, T = Creator<B, void>]’: 
./factory.h:116: instantiated from here 
....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp:187: error: cannot convert ‘CreatorImpl<B, BB, double>*’ to ‘Creator<B, void>*’ in initialization 
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create() [with bT = B, cT = BB, pT = double]’: 
main.cpp:15: instantiated from here 
./factory.h:27: error: no matching function for call to ‘BB::BB()’ 
./class.h:36: note: candidates are: BB::BB(double) 
./class.h:34: note:     BB::BB(const BB&) 
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = B, cT = BB, pT = double]’: 
main.cpp:15: instantiated from here 
./factory.h:28: error: no matching function for call to ‘BB::BB(const double*&)’ 
./class.h:36: note: candidates are: BB::BB(double) 
./class.h:34: note:     BB::BB(const BB&) 
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = A, cT = AA, pT = void]’: 
main.cpp:15: instantiated from here 
./factory.h:28: error: no matching function for call to ‘AA::AA(const void*&)’ 
./class.h:18: note: candidates are: AA::AA() 
./class.h:18: note:     AA::AA(const AA&) 
make: *** [test] Error 1 

任何人都可以用错误的帮助?这是创建通用模板工厂的好方法吗?

+0

这可能会帮助您开始:http://stackoverflow.com/questions/16047560/creating-dynamic-type-in​​-c/16047779#16047779 - 完全不需要太多的模板。 – paddy 2013-05-06 22:16:13

+0

谢谢稻田。但是这并没有解决我的问题。基本上我已经有了工厂,但我只是想重用它来适应创建一个具有零个或一个输入参数的类。 – user2355104 2013-05-06 22:46:04

+0

如果您发布的代码完全从您的项目中复制,则您使用了错误的评论语法。对于单行注释,请使用'//'而不是'/ *'。 – paddy 2013-05-06 23:05:49

回答

0

第一个错误:

typedef boost::shared_ptr< Creator<bT> > type; 

你忘传递点:

typedef boost::shared_ptr< Creator<bT,pT> > type; 

第二:

virtual bT* create(const pT* param) { return new cT(param); } 

要么接受创建引用,或通过取消引用指针到构造函数:

virtual bT* create(const pT& param) { return new cT(param); } // and change the other parts of the code accordingly to accept reference instead of pointer 
// or: 
virtual bT* create(const pT* param) { return new cT(*param); } 

更大的问题是,在这种方法中,两个版本的create都是为给定的cT生成的,并且由于缺少构造函数重载而不会编译。

专门针对void,并且只保留有意义的创建过载。这种方法的工作原理:

#ifndef INCLUDED_CLASS 
#define INCLUDED_CLASS 

#include <iostream> 
#include <boost/shared_ptr.hpp> 


class A 
{ 
public: 
    A() { _a = 27; } 
    void print() const { std::cout << "A is " << _a << "." << std::endl; } 
protected: 
    int _a; 
}; 
typedef boost::shared_ptr<A> APtr; 

class AA : public A 
{ 
public: 
    void print() const { std::cout << "AA is " << _a << "!" << std::endl; } 
}; 

class B 
{ 
public: 
    B(double b) { _b = b; } 
    void print() const { std::cout << "B is " << _b << "." << std::endl; } 
protected: 
    double _b; 
}; 
typedef boost::shared_ptr<B> BPtr; 

class BB : public B 
{ 
public: 
    BB(double b) : B(b) {}; 
    void print() const { std::cout << "BB is " << _b << "!" << std::endl; } 
}; 

#endif 

// ---- 

#ifndef INCLUDED_FACTORY 
#define INCLUDED_FACTORY 

#include <map> 
#include <string> 
#include <boost/shared_ptr.hpp> 

template<class bT, class pT = void> 
class Creator 
{ 
public: 
    virtual bT* create(const pT* param) = 0; 
}; 

template<class bT> 
class Creator<bT> 
{ 
public: 
    virtual bT* create() = 0; 
}; 

template <class bT, class pT = void> 
struct CreatorPtr 
{ 
    typedef boost::shared_ptr< Creator<bT,pT> > type; 
}; 
template <class bT> 
struct CreatorPtr<bT> 
{ 
    typedef boost::shared_ptr< Creator<bT> > type; 
}; 


template <class bT, class cT, class pT = void> 
class CreatorImpl : public Creator<bT, pT> 
{ 
public: 
    virtual bT* create(const pT* param) { return new cT(*param); } 
}; 
template <class bT, class cT> 
class CreatorImpl<bT,cT> : public Creator<bT> 
{ 
public: 
    virtual bT* create() { return new cT; } 
}; 

template<class CreatorPtrType> 
class FactoryBase 
{ 
protected: 
    FactoryBase() {} 
    FactoryBase(const FactoryBase&) {} 
    FactoryBase &operator=(const FactoryBase&) { return *this; } 
    void registerCreator(const std::string& name, CreatorPtrType creator) 
    { _table_creator[name] = creator; } 
    typedef std::map<std::string, CreatorPtrType> tableCreator; 
    typedef typename tableCreator::const_iterator citerTc; 
    citerTc begin() const { return _table_creator.begin(); } 
    citerTc end() const { return _table_creator.end(); } 
    citerTc find(const std::string& name) const { return _table_creator.find(name); } 
protected: 
    tableCreator _table_creator; 
}; 


template<class bT, class pT = void> 
class Factory : public FactoryBase<typename CreatorPtr<bT, pT>::type> 
{ 
public: 
    virtual bT* create(const std::string& name, const pT* param) const = 0; 
}; 
template<class bT> 
class Factory<bT> : public FactoryBase<typename CreatorPtr<bT>::type> 
{ 
public: 
    virtual bT* create(const std::string& name) const = 0; 
}; 

class A; 
class EngineA : public Factory<A> 
{ 
public: 
    virtual A* create(const std::string& name) const 
    { 
     citerTc it = find(name); 
     if (it != end() && it->second) 
     { 
      return it->second->create(); 
     } 
     else 
      return (A*)NULL; 
    } 

    static Factory<A>& get() 
    { 
     static EngineA instance; 
     instance.registerEngine(); 
     return instance; 
    } 
private: 
    virtual void registerEngine(); 
}; 

void EngineA::registerEngine() 
{ 
    CreatorPtr<A>::type AACreator(new CreatorImpl<A, AA>); 
    registerCreator("AA", AACreator); 
} 

class B; 
class EngineB : public Factory<B, double> 
{ 
public: 
    virtual B* create(const std::string& name, const double* value) const 
    { 
     citerTc it = find(name); 
     if (it != end() && it->second && value) 
     { 
      return it->second->create(value); 
     } 
     else 
      return (B*)NULL; 
    } 

    static Factory<B, double>& get() 
    { 
     static EngineB instance; 
     instance.registerEngine(); 
     return instance; 
    } 
private: 
    virtual void registerEngine(); 
}; 

void EngineB::registerEngine() 
{ 
    CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>); 
    registerCreator("BB", BBCreator); 
} 

#endif 

// ---- 

#include <class.h> 
#include <factory.h> 

int main(void) 
{ 
    APtr a(EngineA::get().create("AA")); 
    if (a) 
     a->print(); 

    double value = 35.7; 
    BPtr b(EngineB::get().create("BB",&value)); 
    if (b) 
     b->print(); 

    return 0; 
} 
+0

谢谢。它编译和工作。您能否告诉我如何按照该顺序安装Creator类,是否像第二个类似于前一个类的特例? – user2355104 2013-05-07 14:25:51

+0

是的,这是部分专业化。部分原因是仍然存在一些模板参数。专业化,因为一些参数是固定的。 一般声明是: template class Creator; 专业化是: 模板 类造物主 这相当于: 模板 类造物主 因为默认的说法。 这里pT被固定为无效,而bT仍然是一个参数。 该实现涵盖了pT无效的任何bT。 对于任何其他情况,通用版本将被实例化。 – jmihalicza 2013-05-07 17:34:20

+0

谢谢。这对我来说非常合适,并且受过良好的教育! – user2355104 2013-05-07 18:00:46