构造函数:
类通过一个或几个特殊的成员函数来控制其对象的初始化进程,这些函数叫构造函数。构造函数的任务是初始化类对象的数据成员。
构造函数名字和类名相同,构造函数没有返回类型。构造函数也有一个可能为空的参数列表和一个可能为空的函数体。
构造函数不能被声明成const的,构造函数在const对象的构造过程中可以向其写值。
1.默认构造函数:
- 如果我们没有为对象提供初始值,那么他们执行了默认初始化。类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫默认构造函数。如果我们的类没有显式定义构造函数,编译器隐式的定义一个默认构造函数。
- 默认构造函数按如下规则初始化类的数据成员:如果存在类内的初始值,用它来初始化成员。否则,默认初始化该成员。
- 某些类不能依赖与合成的默认构造函数:
- 编译器只有发现类不包含任何构造函数的情况下,才能替我们生成一个默认的构造函数。一旦我们定义了一些其他的构造函数,除非我们再定义一个默认的构造函数,否则类将没有默认构造函数。
- 对某些类来说,合成的默认构造函数可能执行错误的操作。含有内置类型或复合类型成员的类需要在类的内部初始化这些成员,或者定义一个自己的默认构造函数。否则用户在创建类的对象时采用默认初始化,导致这些对象的值是未定义的。
- 有时编译器不能为某些类合成默认构造函数。如果类中包含一个其他类类型的成员,而且这个成员没有默认构造函数,那么编译器将无法初始化该成员。
2.定义构造函数:
struct Sales_data{Sales_data() = default;Sales_data(const std::string &s) : bookNo(s) { }Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) { }Sales_data(std::istream &);//之前已经有的其他成员std::string isbn() const { return bookNo; }Sales_data& combine(const Sales_data&);double avg_price() const;std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;
};
-
定义默认构造函数:
Sales_data() = default;
该构造函数不接受任何实参,所以他是一个默认构造函数。我们定义这个构造函数的目的是因为我们既需要其他形式的构造函数,也需要默认的构造函数。
如果我们需要默认的行为,可以通过参数列表后面写上 = default 来要求编译器生成构造函数。
=default可以和声明一起出现在类的内部也可以在作为定义出现在类的外部,在内部,默认构造函数是内联的。
-
构造函数初始值列表
Sales_data(const std::string &s) : bookNo(s) { }Sales_data(const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) { }//使用前两个参数初始化bookNo和units_sold,revenue 的初始值通过n和p相乘得到。
:以及:和{}之间的代码,称为构造函数初始值列表。
它负责为新建的对象的一个或几个数据成员赋初值。这个列表是成员名字的一个列表,括号里面是成员初始值,不同成员初始化通过逗号分隔。
只有一个string类型参数的构造函数使用这个string 对象初始化bookNo,对于units_sold和revenue则没有显式初始化,某个数据成语被构造函数初始值列表忽略,它将以与合成默认构造函数相同的方式隐式初始化。
Sales_data(const std::string &s) : bookNo(s) { } //下面与上面的构造函数效果相同: Sales_data(const std::string &s) : bookNo(s), units_sold(0), revenue(0) { }
构造函数唯一目的就是为数据成员赋初值,一旦没有其他任务需要执行,函数体也就空了。
-
构造函数和类内初始值:
我们使用= default来要求编译器生成默认构造函数,是因为我们为内置类型的数据成员提供了初始值,如果编译器不支持类内初始值,那么默认构造函数就应该使用构造函数初始化列表。
如果编译器不支持类内初始值,则所有的构造函数都应该显式初始化每个内置类型成员。
-
在类的外部定义构造函数:
Sales_data::Sales_data(std::istream &is){read(is, *this); }
这个构造函数的构造函数初始值列表是空的,但是由于执行了构造函数体,所以对象的成员仍然能被初始化。
没有出现在构造函数初始值列表中的成员将通过相应的类内初始值初始化,或者执行默认初始化。一旦函数开始执行,bookNo将被初始化为空string对象,units_sold和revenue将是0。