9. 若不想使用编译器自动生成的函数,就该明确的拒绝
#include "stdafx.h"
#include <string>
using namespace std;
class UnCopyAble
{
protected:
UnCopyAble(){}
~UnCopyAble(){}
private:
//放入private,则不允许使用拷贝构造和对象间赋值
//即使不慎在 membre或friend中使用,则链接通不过。
//原因是只有声明
UnCopyAble(const UnCopyAble&);
UnCopyAble& operator=(const UnCopyAble &);
};
class HomeForSale : private UnCopyAble //class 不再声明copy构造函数和赋值重载
{
public:
};
int _tmain(int argc, _TCHAR* argv[])
{
HomeForSale sale1;
//以下将不允许
HomeForSale sale2(sale1);
//以下将不允许
HomeForSale sale3;
sale3 = sale1;
return 0;
}
10.为多态基类声明virtual析构函数
总结:带有多态性质的基类应该声明一个virtual析构函数。如果class带有任何virutal,它也应该拥有一个virtual析构函数。
class设计目的不是作为基类来使用的,或不是为了具备多态性,就不应该声明virutal析构函数(一个类如果加入了virutal函数,则类大小
会发生变化。因为有包含virutal table pointer)。
11. 别让异常逃离析构函数
析构函数绝对不要吐出异常,这样会带来“过早结束程序”或“发生不明确行为”。如果一个析构函数可能要抛出异常,析构函数应该捕捉任何异常,然后吞下
它,或者结束程序。如果要在某个函数运行时抛出的异常做出反应,那么class应该提供一个普通函数执行这个操作。例如下:
class DBConn
{
public:
//供客户使用的函数
void Close()
{
db.close();
closed =
true;
}
~DBConn()
{
if(!closed)
{
try
{
db.close();
//关闭连接,如果客户不调用Close的话
}
catch (
)
{
//写入日志,记下close调用失败
}
}
}
private:
DBConnection db;
bool closed;
12. 绝不在构造和析构过程中调用virtual函数
// testss.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <
string>
#include <list>
using namespace std;
class Transaction
{
public:
Transaction();
void init();
virtual void logTranscation() = 0;
};
Transaction::Transaction()
{
init();
}
void Transaction::init()
{
logTranscation();
}
class BuyTransaction :
public Transaction
{
public:
void logTranscation()
{
printf("BuyTransaction log
\n");
}
};
int _tmain(
int argc, _TCHAR* argv[])
{
BuyTransaction b;
return 0;
}
以上代码,会有一个BuyTransaction构造函数被调用,但首先是Transaction更早被调用。在derived class对象的base class构造期间,对象的类型是base class.若使用运行期类型信息,也会把对象视为base class类型。本例,构造函数中调用init,而init中调用Transaction::logTransaction。而logTransaction又是抽象方法,导致程序异常中止。当然如果非抽象方法,则会调用Transaction中的logTransaction。
同样,析构函数,一旦derived class析构函数先开始执行。对象内的derived class成员变量便呈现现未定义值。所以c++视它们不存在。进入base class析构函数后对象就成为一个base class对象。
13. 令operator=返回一个reference to *this
14. 在operator=中处理“自我赋值”