1、了解C++默默编写并调用哪些函数
*至于copy构造函数和copy assignment操作符,编译器创建的版本只是单纯地将来源对象的每一个non-static 成员变量拷贝到目标对象。注意,编译器产出的析构函数是个non-virtual。
*如果你打算在一个"内含reference 成员"的 class 内支持赋值操作 (assignment) ,你必须自己定义 copy assignment 操作符。面对"内含 const 成员" (如本例之 objectValue) 的classes ,编译器的反应也一样。更改 const 成员是不合法的,所以编译器不知道如何在它自己生成的赋值函数内面对它们。最后还有一种情况:如果某个 base classes 将copy assignment 操作符声明为 private ,编译器将拒绝为其 derived classes 生成一个 copy assignment 操作符。毕竟编译器为 derived classes 所生的 copy assignment 操作符想象中可以处理 base class 成分 ,但它们当然无法调用 derived class 无权调用的成员函数。
2、若不想使用编译器自动生成的函数,就该明确拒绝
方法一:直接将本类的copy构造函数和copy assignment操作符声明为private;
方法二:设计一个专门为了阻止copying动作的baseclass,让那些不想使用编译器自动生成类继承这具baseclass.实现如下:
class Uncopyable
{
protected: //允许derived对象构造和析构
Uncopyable() {}
-Uncopyable(} { }
private:
Uncopyable(constUncopyable&}; //但阻止copying
Uncopyable& operator=(constUncopyable&);
};
class D:private Uncopyable
{...};
只要任何人一一甚至是member函数或friend函数一一尝试拷贝D对象,编译器便试着生成一个copy构造函数和-个copyass够nment操作符,而正如条款12所说,这些函数的"编译器生成版"会尝试调用其base class的对应兄弟,那些调用会被编译器拒绝,因为其baseclass的拷贝函数是private。
3、为多态墓类声明virtual析构函数
*通过指针指向一个derived class 对象 ,而那个对象却经由一个base class指针被删除,而目前的baseclass 有个non-virtual析构函数。那么,实际执行时通常发生的是对象的 derived 成分没被销毁。derived class的析构函数也没有被执行起来。从而使对象只是被局部撤销。解决方法:给baseclass一个virtual析构函数。
*不要继承STL中定义的类型和容器,因为他们不是设计成基类来用作继承的,它们的析构函数是不带virtual的。
*而有时候你希望拥有抽象class,但手上没有任何pure virtual函数,怎么办?解决方法:由于抽象class总是企图被当作一个baseclass来用,而又由于baseclass应该有个virtual析构函数,并且由于pure virtual函数会导致抽象class,因此解法很简单:为你希望它成为抽象的那个class声明一个pure virtual
析构函数。
4、到让异常逃离析构函数
*析构函数绝对不要吐出异常。如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序。
*如果客户需要对某个操作函数运行期间抛出的异常做出反应,那么 class 应该提供一个普通函数(而非在析构函数中)执行该操作。
class DBConn
{
public:
void close( ) //供客户使用的新函数
{
db.close( );
closed = true;
}
~DBConn ()
{
if (! closed) {
try { //关闭连接(如果客户不那么做的话)
db. close( );
}
catch (...) {
制作运转记录,记下对close的调用失败;
//如果关闭动作失败,
// 记录下来并结束程序
// 或吞下异常。
}
}
}
private:
DBConnection db;
bool closed;
};
5、绝不在构造和析构过程申调用 virtual 函数
*base class 构造期间virtual 函数绝不会下降到derived classes阶层。取而代之的是,对象的作为就像隶属base类型一样。非正式的说法或许比较传神:在baseclass构造期间,virtual函数不是virtual函数。
*原因:1、由于base class 构造函数的执行更早于derivedclass构造函数,当baseclass构造函数执行时derivedclass的成员变量尚未初始化。如果此期间调用的virtual函数下降至derivedclasses阶层,要知道derivedclass的函数几乎必然取用local成员变量,而那些成员变量尚未初始化。2、在derivedclass对象的baseclass构造期间,对象的类型是 base class 而不是 derived class。
*注意:很多时候为了避免代码重复,把virtual函数放在另一个函数中,但构造和析构函数中调用此函数,则此错误就更隐蔽,更难发现。
6、复制对象时勿忘其每一个成分
*Copying函数应该确保复制"对象内的所有成员变量"及"所有baseclass成分"。
*不要尝试以某个copying函数实现另一个copying函数。应该将共同机能放进第三个函数中,并由两个coping函数共同调用。