C++ 我是否可以在不使用new()的情况下实现工厂模式构建?

C++ 我是否可以在不使用new()的情况下实现工厂模式构建?,c++,initialization,factory-pattern,C++,Initialization,Factory Pattern,目前,我正在处理一个令人愉快的遗留代码类,它通过开关大小写实现多态性: class-LegacyClass{ 公众: 枚举初始化类型{TYPE_A,TYPE_B}; void init(InitType type){m_type=type;} int foo(){ if(m_type==类型A) { /*…特定工作*/ 返回1; } //否则,键入_B: /*…特定于B的工作*/ 返回2; } /**还有很多类似的功能**/ 私人: InitType m_类型; }; 我想将其重构为适当的多

目前,我正在处理一个令人愉快的遗留代码类,它通过开关大小写实现多态性:

class-LegacyClass{
公众:
枚举初始化类型{TYPE_A,TYPE_B};
void init(InitType type){m_type=type;}
int foo(){
if(m_type==类型A)
{ 
/*…特定工作*/
返回1;
}
//否则,键入_B:
/*…特定于B的工作*/
返回2;
}
/**还有很多类似的功能**/
私人:
InitType m_类型;
};
我想将其重构为适当的多态性,例如:

类重构类{
公众:
虚拟~RefacturedClass(){}
虚拟int foo()=0;
};
类\u ImplA:公共重构类{
公众:
虚拟~Class_ImplA(){}
int foo(){
/*…特定工作*/
返回1;
}
};
类\u ImplB:公共重构类{
公众:
虚拟~Class_ImplB(){}
int foo(){
/*…特定于B的工作*/
返回2;
}
};
不幸的是,我有一个关键问题:由于优化和架构方面的考虑,在主要使用
LegacyClass
时,我不能使用动态分配;该实例是按组合划分的不同类的成员:

类BigImportantClass{
/* ... */
私人:
LegacyClass m_遗产;
}
(在本例中,
BigImportantClass
可以动态分配,但分配需要在一个连续的虚拟段中,并且需要一个
new()
调用;我不能在
BigImportantClass
ctor或后续初始化方法中进一步调用
new()

是否有一种不使用
new()
而以多态方式初始化具体实现的好方法?



到目前为止,我自己的进展是:我能做的是提供一个
char[]
缓冲区作为
bigmentrantclass
的成员,并以某种方式初始化该内存中的
重构类的具体成员。缓冲区将足够大,可以容纳
重构类的所有实现。然而,我不知道如何安全地做到这一点。我知道新语法的位置,但我不熟悉处理对齐(因此,被警告不要这样做),对于
refacturedclass
接口的所有具体实现,一般地对齐听起来令人畏惧。这是路吗?或者我还有其他选择吗?

现在应该有人回答了……这是我的

我建议使用字符数组的并集和最大的整数类型之一:

union {
    char refactored_class_buffer[ sizeof RefactoredClass ];
    long long refactored_class_buffer_aligner;
};

我还强烈建议使用断言,甚至是if(check)抛出;如果每种情况下的数据都相同,并且您只是在改变行为,您不需要在核心中进行分配-这基本上是一种使用单例策略的策略模式。最终在逻辑中使用多态性,而不是在数据中使用多态性

class FooStrategy() {
virtual int foo(RefactoredClass& v)=0;
}

class RefactoredClass {
   int foo() {
     return this.fooStrategy(*this);
   }
   FooStrategy * fooStrategy;
};

class FooStrategyA : public FooStrategy {

   //Use whichever singleton pattern you're happy with.
   static FooStrategyA* instance() {
      static FooStrategyA fooStrategy;
      return &fooStrategy;
   }

   int foo(RefactoredClass& v) {
      //Do something with v's data
   }
}

//Same for FooStrategyB

然后,当您创建一个
RefacturedClass
时,将其
FooStrategyA
设置为
FooStrategyA::instance()

以下是一些代码。。。只是做一些显而易见的事情。我不使用,这实际上可能是一种更结构化的方法,可以确保适当的对齐和大小,并清理代码

#include <iostream>

template <size_t A, size_t B>
struct max
{
    static const size_t value = A > B ? A : B;
};

class X
{
  public:
    X(char x) { construct(x); }

    X(const X& rhs)
        { rhs.interface().copy_construct_at_address(this); }

    ~X() { interface().~Interface(); }

    X& operator=(const X& rhs)
    {
        // warning - not exception safe
        interface().~Interface();
        rhs.interface().copy_construct_at_address(this);
        return *this;
    }

    struct Interface
    {
        virtual ~Interface() { }
        virtual void f(int) = 0;
        virtual void copy_construct_at_address(void*) const = 0;
    };

    Interface& interface()
        { return reinterpret_cast<Interface&>(data_); }

    const Interface& interface() const
        { return reinterpret_cast<const Interface&>(data_); }

    // for convenience use of virtual members...
    void f(int x) { interface().f(x); }

  private:
    void construct(char x)
    {
             if (x == 'A') new (data_) Impl_A();
        else if (x == 'B') new (data_) Impl_B();
    }

    struct Impl_A : Interface
    {
        Impl_A() : n_(10) { std::cout << "Impl_A(this " << this << ")\n"; }
        ~Impl_A() { std::cout << "~Impl_A(this " << this << ")\n"; }
        void f(int x)
            { std::cout << "Impl_A::f(x " << x << ") n_ " << n_;
              n_ += x / 3;
              std::cout << " -> " << n_ << '\n'; }
        void copy_construct_at_address(void* p) const { new (p) Impl_A(*this); }
        int n_;
    };

    struct Impl_B : Interface
    {
        Impl_B() : n_(20) { std::cout << "Impl_B(this " << this << ")\n"; }
        ~Impl_B() { std::cout << "~Impl_B(this " << this << ")\n"; }
        void f(int x)
            { std::cout << "Impl_B::f(x " << x << ") n_ " << n_;
              n_ += x / 3.0;
              std::cout << " -> " << n_ << '\n'; }
        void copy_construct_at_address(void* p) const { new (p) Impl_B(*this); }
        double n_;
    };

    union
    {
        double align_;
        char data_[max<sizeof Impl_A, sizeof Impl_B>::value];
    };
};

int main()
{
    {
        X a('A');
        a.f(5);

        X b('B');
        b.f(5);
        X x2(b);
        x2.f(6);
        x2 = a;
        x2.f(7);
    }
}

我使用C++11联合实现了这一点。这段代码似乎在g++4.8.2下工作,但它需要-std=gnu++11或-std=c++11标志

#include <iostream>

class RefactoredClass {
  public:
  virtual ~RefactoredClass() { }; // Linking error if this is pure.  Why?
  virtual int foo() = 0;
};

class RefactorA : RefactoredClass {
  double data1, data2, data3, data4;

  public:
  int foo() { return 1; }
  ~RefactorA() { std::cout << "Destroying RefactorA" << std::endl; }
};

class RefactorB : RefactoredClass {
  int data;

  public:
  int foo () { return 2; }
  ~RefactorB() { std::cout << "Destroying RefactorB" << std::endl; }
};

// You may need to manually create copy, move, &ct operators for this.
// Requires C++11
union LegacyClass {
  RefactorA refA;
  RefactorB refB;

  LegacyClass(char type) { 
    switch (type) {
      case 'A':
        new(this) RefactorA;
        break;
      case 'B':
        new(this) RefactorB;
        break;
      default:
        // Rut-row
        break;
    }
  }

  RefactoredClass * AsRefactoredClass() { return (RefactoredClass *)this; }

  int foo() { return AsRefactoredClass()->foo(); }

  ~LegacyClass() { AsRefactoredClass()->~RefactoredClass(); }

};

int main (void) {
  LegacyClass A('A');
  LegacyClass B('B');

  std::cout << A.foo() << std::endl;
  std::cout << B.foo() << std::endl;

  return 0;
}
#包括
类重构类{
公众:
virtual~refacturedClass(){};//如果这是纯链接错误。为什么?
虚拟int foo()=0;
};
类重构A:RefacturedClass{
双数据1,数据2,数据3,数据4;
公众:
int foo(){return 1;}

~RefactorA(){std::您是否可以将多态层次结构保持为某个环境类的私有,并且只在内部使用动态分配。如果您知道在
BigImportantClass
构造函数之前需要哪个实现,您可能可以使用一个模板。@Wimmel:我正在考虑一个模板-那会很快!-但这意味着要拖动impl将校正选项提高到一个更可见的级别(
BigImportantClass
变为
BigImportantClass
)。但这绝对是一个选项。@Ziv您可以在工厂函数中隐藏实现选项,如
CreateBigImportantClass()
,它甚至可以是静态成员。您确实意识到这一点,任何对小型函数的虚拟分派都可能比传统交换机慢得多?无论如何,不要放置
char[]
BigImportantClass
中,将
LegacyClass
替换为嵌入对齐缓冲区的类。您可能可以使用
double
char[]的并集
-几乎没有什么比
double
更需要对齐的了。替换类应该有一个函数来获取放置的引用或指针-
新对象。+1-不错;-)“如果这是纯链接错误。为什么?”-当对象被销毁时,析构函数从大多数派生类运行回基类…销毁任何数据成员,将指向虚拟分派表的指针也设置回基类,以便不使用已销毁的派生类级别的重写。。。。
#include <iostream>

class RefactoredClass {
  public:
  virtual ~RefactoredClass() { }; // Linking error if this is pure.  Why?
  virtual int foo() = 0;
};

class RefactorA : RefactoredClass {
  double data1, data2, data3, data4;

  public:
  int foo() { return 1; }
  ~RefactorA() { std::cout << "Destroying RefactorA" << std::endl; }
};

class RefactorB : RefactoredClass {
  int data;

  public:
  int foo () { return 2; }
  ~RefactorB() { std::cout << "Destroying RefactorB" << std::endl; }
};

// You may need to manually create copy, move, &ct operators for this.
// Requires C++11
union LegacyClass {
  RefactorA refA;
  RefactorB refB;

  LegacyClass(char type) { 
    switch (type) {
      case 'A':
        new(this) RefactorA;
        break;
      case 'B':
        new(this) RefactorB;
        break;
      default:
        // Rut-row
        break;
    }
  }

  RefactoredClass * AsRefactoredClass() { return (RefactoredClass *)this; }

  int foo() { return AsRefactoredClass()->foo(); }

  ~LegacyClass() { AsRefactoredClass()->~RefactoredClass(); }

};

int main (void) {
  LegacyClass A('A');
  LegacyClass B('B');

  std::cout << A.foo() << std::endl;
  std::cout << B.foo() << std::endl;

  return 0;
}