14 September 2022

C++ 核心指南目录

C.40: Define a constructor if a class has an invariant

理由

构造函数的目的就是为了建立类中数据的不变式约束条件。

例如

class Date {  // a Date represents a valid date
              // in the January 1, 1900 to December 31, 2100 range
    Date(int dd, int mm, int yy)
        :d{dd}, m{mm}, y{yy}
    {
        if (!is_valid(d, m, y)) throw Bad_date{};  // enforce invariant
    }
    // ...
private:
    int d, m, y;
};

最好通过构造函数来表达某种固定约束。

注意

就算类中没有固定约束,为了使用方便,也会用到构造函数。

struct Rec {
    string s;
    int i {0};
    Rec(const string& ss) : s{ss} {}
    Rec(int ii) :i{ii} {}
};

Rec r1 {7};
Rec r2 {"Foo bar"};

注意

很多情况下,C++11 的初始化列表,可以减少构造函数。

struct Rec2{
    string s;
    int i;
    Rec2(const string& ss, int ii = 0) :s{ss}, i{ii} {}   // redundant
};

Rec2 r1 {"Foo", 7};
Rec2 r2 {"Bar"};

Rec2 的构造函数就是多余的了。这个构造函数中 ii 的默认值,最好在成员定义的时候进行初始化。

强化

  • 标记那些有自定义的复制操作,却没有构造函数的类。自定义的复制造作意味着类中有某种固定结构。