C++ 在c+中实现一个通用的构建器模式+;

C++ 在c+中实现一个通用的构建器模式+;,c++,c++11,design-patterns,C++,C++11,Design Patterns,我决定使用模式来避免长的未命名参数构造函数,但我有一个特定的用例。我有一个基类和一些继承的类,它们都必须能够单独构造。下面显示一段伪代码,解释我的特殊用例: class B { int i; int j; public: B& setI(int i) {this->i=i; return *this;} B& setJ(int j) {this->j=j; return *this;} } class I : public B { int i2;

我决定使用模式来避免长的未命名参数构造函数,但我有一个特定的用例。我有一个基类和一些继承的类,它们都必须能够单独构造。下面显示一段伪代码,解释我的特殊用例:

class B
{
  int i;
  int j;
public:
  B& setI(int i) {this->i=i; return *this;}
  B& setJ(int j) {this->j=j; return *this;}
}

class I : public B
{
  int i2;
  int j2;
public:
  I& setI2(int i) {this->i2=i; return *this;}
  I& setJ2(int j) {this->j2=j; return *this;}
}
B b = B().setI(12).setJ(13); // ok
I i = I().setI(12).setJ(13).setI2(14).setJ2(15); // error the first and second function return B not I
无法编译上述代码,因为B中的函数不返回类I的类型。中建议了一种解决方案,但它是有限的,并且不可能单独创建基类。 我使用C++ 11,但是可以使用另一个版本的C++。 更新:


有一种解决方案可以接受B作为I的构造函数的参数,但在实际问题中,存在一些继承层,使用这种解决方案不是很实用。

我们可以为类
I
创建一个
Builder
,最终分配类
I
及其基类
B
的属性。
Builder
应该是类
I
的朋友,这样我们就可以访问
Builder
的受保护成员,并且我们还可以确保
Builder
的所有属性都可用

考虑类
B

class B {
protected:
  int first;
  int second;

public:
  int get_first() { return this->first; }

  int get_second() { return this->second; }
};
I

class I : public B {
  int third;
  int fourth;

public:
  int get_third() { return this->third; }

  int get_fourth() { return this->fourth; }

  class Builder : public B {
    int third;
    int fourth;

  public:
    Builder &set_first(const int &first) {
      this->first = first;
      return *this;
    }

    Builder &set_second(const int &second) {
      this->second = second;
      return *this;
    }

    Builder &set_third(const int &third) {
      this->third = third;
      return *this;
    }

    Builder &set_fourth(const int &fourth) {
      this->fourth = fourth;
      return *this;
    }

    friend class I;
  };

  I(const Builder &builder);
};
因此,它允许我们为属性赋值:

I::I(const I::Builder &builder) {
  this->first = builder.first;
  this->second = builder.second;
  this->third = builder.third;
  this->fourth = builder.fourth;
}
示例

int main() {
  I::Builder builder;

  I i = builder.set_first(100).set_second(102);
  std::cout << "[sample 1] first: " << i.get_first() << "\n";
  std::cout << "[sample 1] second: " << i.get_second() << "\n";
  std::cout << "[sample 1] third: " << i.get_third() << "\n";
  std::cout << "[sample 1] fourth: " << i.get_fourth() << "\n";
  std::cout << "\n";

  i = builder.set_first(12).set_second(13).set_third(14).set_fourth(15);
  std::cout << "[sample 2] first: " << i.get_first() << "\n";
  std::cout << "[sample 2] second: " <<  i.get_second() << "\n";
  std::cout << "[sample 2] third: " << i.get_third() << "\n";
  std::cout << "[sample 2] fourth: " << i.get_fourth() << "\n";
  std::cout << "\n";

  i = builder.set_first(1).set_third(3);
  std::cout << "[sample 3] first: " << i.get_first() << "\n";
  std::cout << "[sample 3] second: " << i.get_second() << "\n";
  std::cout << "[sample 3] third: " << i.get_third() << "\n";
  std::cout << "[sample 3] fourth: " << i.get_fourth() << "\n";

  return 0;
}
[sample 1] first: 100
[sample 1] second: 102
[sample 1] third: 0
[sample 1] fourth: 0

[sample 2] first: 12
[sample 2] second: 13
[sample 2] third: 14
[sample 2] fourth: 15

[sample 3] first: 1
[sample 3] second: 13
[sample 3] third: 3
[sample 3] fourth: 15