高效的施工授权

时间:2018-01-19 17:03:47

标签: c++ c++11 c++14

我一直在思考构造函数委派以及如何在没有代码重复的情况下有效地进行构建。

让我们考虑以下

代码示例101

委托给def cons但委托构造函数必须传入虚拟空值。问题是它容易出错和杂乱。

class A
{
    int a1;
    double a2;
    string a3;
    DatabaseHandle* p;

public:
    A(int i=0, double d=0.0, string s="") : a1(i), a2(d), a3(s) {
        //open data base connection
    }
    A(int i) : A(i) {}
    A(double d) : A(0,d) {}
    A(string s) : A(0,0.0,s) {}  
}

代码示例102

语法更清晰,但效率不如101.委托构造函数重新赋值。

class A
{
    int a1;
    double a2;
    string a3;
    DatabaseHandle* p;

public:
    A(int i=0, double d=0.0, string s="") : a1(i), a2(d), a3(s) {
         //open database
    }
    A(int i) : A() { a1=i; }
    A(double d) : A() { a2=d;}
    A(string s) : A() { a3=s;}  
}

代码示例103

没有超过102的改进,实际上需要1个额外的构造函数。所以减少代码精简。

class A
{
    int a1 = 0;
    double a2 = 0.0;
    string a3 = "";
    DatabaseHandle* p;

public:
    A() { //open database
    }
    A(int i) : A() { a1=i; }
    A(double d) : A() { a2=d;}
    A(string s) : A() { a3=s;} 
    A(int i, double d, string s) : a1(i), a2(d), a3(s) {}
}

问题: 有没有办法修复这个代码,以便(1)很少或没有代码重复(2)不必将虚拟占位符值传递给构造函数参数(3)不需要重新赋值?

假设min C ++版本是C ++ 11。

注意/编辑: 我添加了DatabaseHandle * p,以澄清def构造函数有一些逻辑来设置。我想澄清一下,构造函数有一些共同的工作要做。如果在原帖中不清楚,我道歉。

2 个答案:

答案 0 :(得分:1)

无需链接到默认构造函数即可应用默认成员初始值设定项。它们会在任何没有给它们显式初始化器的构造函数中起作用。

class A
{
    int a1 = 0;
    double a2 = 0.0;
    string a3 = "";

public:
    A() {}
    A(int i) : a1(i) {}
    A(double d) : a2(d) {}
    A(string s) : a3(s) {}
};

答案 1 :(得分:1)

简单:

class A  {
  int a1 = 0;
  double a2 = 0.0;
  std::string a3 = "";
  upDBHandle p = open_database(a1, a2, a3);
public:
  A() = default;
  explicit A(int i):a1(i) {}
  explicit A(double d):a2(d) {}
  explicit A(std::string s):a3(std::move(s)) {} 
  A(int i, double d, std::string s) : a1(i), a2(d), a3(std::move(s)) {}
};

假设:

struct DatabaseHandle {};

using upDBHandle = std::unique_ptr<DatabaseHandle>;

upDBHandle open_database( int a, double d, std::string const& s ) {
  return std::make_unique<DatabaseHandle>();
}

或同等的。

或:

struct A_settings {
  int a1 = 0;
  double a2 = 0.0;
  std::string a3 = "";
};

struct DatabaseHandle {};

using upDBHandle = std::unique_ptr<DatabaseHandle>;

upDBHandle open_database( int a, double d, std::string const& s ) {
  return std::make_unique<DatabaseHandle>();
}

class A  {
  A_settings settings;
  upDBHandle p = open_database(settings.a1, settings.a2, settings.a3);
public:
  A() = default;
  explicit A(A_settings s) : settings(std::move(s)) {}
};

如果要设置某些字段子集,调用者可以创建各种有意义的A_settings工厂函数。如果这没有任何好处,你可以将每个元素的ctors移动到它。