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=中處理“自我賦值”