具有不同参数的对象工厂

时间:2011-07-07 16:00:40

标签: c++ function pointers function-pointers factory-pattern

我一直在寻找工厂方法,并努力寻找解决我的问题的方法(虽然我感觉它很直接。我正在尝试创建来自同一派生类的对象,这是在提前,但他们有不同的参数。

class Base
{
public:
    Base(){};
    ~Base(){};

    std::string name;
    double base_input;
    double output;

    virtual void relation_function()=0;
};

class Derived1 : public Base 
{
public:
    double private_input;
    int multiplier;

    Derived1(std::string , double , double , int);
    ~Derived1(){};

    virtual void relation_function();
};

class Derived2 : public Base 
{
public:
    double private_input;
    int multiplier;

    Derived2(std::string , double , int);
    ~Derived2(){};

    virtual void relation_function();
};

根据构造函数将参数注入派生类中。

 Derived1::Derived1(std::string input_name, double input_base_input,double input_private_input, 
int input_multiplier){
    name=input_name;
    base_input=input_base_input;
    private_input=input_private_input;
    multiplier=input_multiplier;
 };



Derived2::Derived2(std::string input_name,double input_private_input,int input_multiplier)
    {
        name=input_name;
        private_input=input_private_input;
        multiplier=input_multiplier;
    void relation_function();};
    void Derived2:: relation_function(){output=multiplier*private_input;};


void Derived1:: relation_function(){output=multiplier*base_input*private_input;};

目前我正在手动创建派生类的实例,如下所示

std::vector<std::string> v(3);
v[0]="a";v[1]="b";v[2]="c";
for (int n=0;n<=2;n++)
Base* pderived1(new Derived1(v[n],2,2,1));

std::vector<std::string> v(2);
v[0]="d";v[1]="e";
for (int n=0;n<=1;n++)
Base* pderived1(new Derived1(v[n],5,9,9));

这是不理想的,我需要首先创建一个指向派生类的构造函数的指针,以便在从每个派生类创建多个实例之前,“修复”/“冻结”构造函数中的一些参数。

base* (*pconstructor){string, double, double, int) = Derived (string, 2,2,1)

目标是使用此指针作为主要工具,在传递给以下函数以创建对象之前指定参数。下面的函数将充当工厂来创建derived1或derived所需的实例/对象的数量,这些实例/对象在其构造函数(如derived2)中可能具有不同的参数。

base* function(std::vector<string>){ create instances.. }

我不知道如何创建指针来操纵构造函数参数,也不知道将用于创建实例的函数..任何线索,请.. 非常感谢大家提供c ++新手的帮助!

2 个答案:

答案 0 :(得分:0)

从问题来看,目前还不清楚实际目标是什么。但是,我不知道你是否可以指向构造函数/析构函数的成员函数。所以你必须放弃这个选择。

最好在构造函数实例本身进行任何检查。以下是一个坏主意,因为它泄漏了内存:

for (int n=0;n<=1;n++)
  Base* pderived1(new Derived1(v[n],5,9,9));

您不止一次覆盖pderived1。谨慎使用new / malloc

答案 1 :(得分:0)

解决这个问题的好方法就是提供具有不同参数的函数:

#include <string>
#include <typeinfo>
#include <vector>
class FactoryFunction;

class Factory {
public:
   template<class T, class P1, class P2>
   void reg2(T (*fptr)(P1, P2));
   template<class T, class P1, class P2, class P3>
   void reg3(T (*fptr)(P1,P2,P3));
   template<class T, class P1, class P2, class P3, class P4>
   void reg4(T (*fptr)(P1,P2,P3,P4));
private:
    std::vector<FactoryFunction*> vec;
};
Base *derived1_factory(std::string s, double d1, double d2, int i)
 {
  return new Derived1(s,d1,d2,i);
 }
int main() {
   Factory f;
   f.reg4(&derived1_factory);
}

编辑:此设计还需要一些可能难以理解的内容,特别是以下类:

class FactoryFunction {
public:
   virtual int NumParams() const=0;
   virtual void set_parameter(int i, void *p)=0; 
   virtual std::string parameter_type(int i) const=0;
   virtual void *return_value() const=0;
   virtual std::string return_type() const=0;
};
template<class T, class P1>
class FactoryFunction1 : public FactoryFunction
{
 public:
    FactoryFunction1(T (*fptr)(P1)) : fptr(fptr) { }
    int NumParams() const { return 1; }
    void set_parameter(int i, void *p) { switch(i) { case 0: param1 =*(P1*)p; break; }; }
    std::string parameter_type(int i) const { switch(i) { case 0: return typeid(P1).name(); }; }
    void *return_value(int i) const { return_val = fptr(param1); return (void*)&return_val; }
    std::string return_type() const { return typeid(T).name(); }
private:
    T (*fptr)(P1);
    T return_val;
    P1 param1;
};

然后可以实现像reg1这样的函数来将new FactoryFunction1<T,P1>(fptr)存储到std::vector<FactoryFunction*>。 显然reg1 / reg2 / reg3函数也可以将std :: string作为参数。

编辑:哦,reg4只是缺少实现(你还需要实现其他功能)。

       template<class T, class P1, class P2, class P3, class P4>
       void Factory::reg4(T (*fptr)(P1,P2,P3,P4))
           {
           vec.push_back(new FactoryFunction4(fptr));
           }

让我们希望它现在可以编译:)