几乎每一个class都会有一个或多个构造函数,一个析构函数,一个copy assignment操作符。必须保证它们的行为正确。本文提供的引导可以让你将这些函数良好的集结在一起,形成classes的脊柱。
- 了解C++默默编写并调用了哪些函数
当你声明一个空类时,编译器就会为它声明一个copy构造函数,一个copy assignment操作符和一个析构函数。此外如果你没有声明任何构造函数,编译器也会为你声明一个default构造函数。这些函数都是public且inline
|
|
default构造函数和析构函数主要是给编译一个用来放置幕后代码(比如调用base classes和non-static成员变量的构造和析构函数)的地方,注意,编译器产生的析构函数是non-virtual的。
至于copy构造函数和copy assignment操作符,编译器创建的版本只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象(浅拷贝)。
当类中含有引用、常量成员变量时,编译器将会拒绝自动生成copy构造函数和copy assignment操作符。因为引用在第一次指向对象之后,就不允许被修改为指向不同对象,而常量就更显而易见了。另外,当base classes将copy assignment操作符声明为private,那么编译器同样将拒绝为其派生类生成一个copy assignment操作符。
请记住:
- 编译器可以暗自为class创建default构造函数,copy构造函数,copy assignment操作符,以及析构函数。
- 若不想使用编译器自动生成的函数,就应该明确拒绝
声明函数为private,并且不实现他们(即定义)。即使在member函数或friend函数之内使用它们,连接器会因为找不到其具体实现而报错。
如果希望在编译时期就报错,那么可以通过继承关系来实现,即将基类的copy构造函数和copy assignment操作符声明为private,当任何人尝试拷贝派生类对象时,编译器自动生成的函数会尝试调用其基类的函数,此时编译器就会报错。
- 绝不在构造和析构过程中调用virtual函数
|
|
base class构造期间virtual函数绝对不会下降到derived class.非正式的说法或许比较传神:在base class构造期间,virtual函数不是virtual函数。其真正原因是:base class构造期间derived class对象实体并没有构造出来,其vbtl同样没有被构造出来,因此如果此时virtual函数访问derived class内定义,将产生为定义行为,这是很危险。在derived class对象在base class构造期间,其对象的类型是base class。不只virtual函数会被编译器解析至base class,若使用运行期类型信息(如dynamic_cast, typeid),也会把对象视为base class类型。 相同的道理也适用于析构函数。
- 令operator= 返回一个reference to *this
|
|
同时在赋值操作时,需要额外考虑这样一种情况:“自我赋值”
|
|
- 复制对象时勿忘其每一个成分
- 复制所有local成员变量
- 调用所有base classes内的适当的copying函数
- 不要尝试以某个copying函数实现另一个copying函数。应将共同机能放进第三个函数中,并由两个copying函数共同调用。