Объект Фабрика с разными параметрами - PullRequest
1 голос
/ 07 июля 2011

Я смотрел на фабричный метод и изо всех сил пытался найти решение моей проблемы (хотя у меня есть ощущение, что это прямо. Я пытаюсь создать объекты, которые происходят из того же производного класса, который известен в заранее, но у них разные параметры.

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)

цель состоит в том, чтобы использовать этот указатель на конструктор в качестве основного инструмента для определения параметров перед передачей следующих функций для создания объекта. приведенная ниже функция будет действовать как фабрика для создания количества экземпляров / объектов, требуемых от производного1 или производного, которые могут иметь различные параметры в своих функциях-конструкторах, например, производных2.

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

Я не знаю, как создать указатель для управления параметрами конструктора или функцию, которая будет использоваться для создания экземпляров. Любые подсказки, пожалуйста .. Спасибо всем заранее за помощь от начинающего c ++!

Ответы [ 2 ]

0 голосов
/ 07 июля 2011

Хорошим решением этой проблемы является просто предоставление функций с различными параметрами:

#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));
           }

Будем надеяться, что он скомпилируется сейчас:)

0 голосов
/ 07 июля 2011

Из вопроса неясно, какова реальная цель.Тем не менее, я не знаю, если вы можете иметь указатель на функцию-член для конструктора / деструктора.Таким образом, вы должны отказаться от этой опции.

Лучше делать любую проверку во время самого экземпляра конструктора.Следующее также является плохой плохой идеей, так как утечка памяти:

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

Вы перезаписываете pderived1 более одного разаОсторожно с использованием new / malloc.

...