程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> 高質量C++/C編程指南-第9章-類的構造函數、析構函數與賦值函數(3

高質量C++/C編程指南-第9章-類的構造函數、析構函數與賦值函數(3

編輯:vc教程

9.3 構造和析構的次序
構造從類層次的最根處開始,在每一層中,首先調用基類的構造函數,然後調用成員對象的構造函數。析構則嚴格按照與構造相反的次序執行,該次序是唯一的,否則編譯器將無法自動執行析構過程。

一個有趣的現象是,成員對象初始化的次序完全不受它們在初始化表中次序的影響,只由成員對象在類中聲明的次序決定。這是因為類的聲明是唯一的,而類的構造函數可以有多個,因此會有多個不同次序的初始化表。如果成員對象按照初始化表的次序進行構造,這將導致析構函數無法得到唯一的逆序。[Eckel, p260-261]

9.4 示例:類String的構造函數與析構函數
// String的普通構造函數

String::String(const char *str)

{

if(str==NULL)

{

m_data = new char[1];

*m_data = ‘\0’;

}

else

{

int length = strlen(str);

m_data = new char[length+1];

strcpy(m_data, str);

}

}

// String的析構函數

String::~String(void)

{

delete [] m_data;

// 由於m_data是內部數據類型,也可以寫成 delete m_data;

}

9.5 不要輕視拷貝構造函數與賦值函數
由於並非所有的對象都會使用拷貝構造函數和賦值函數,程序員可能對這兩個函數有些輕視。請先記住以下的警告,在閱讀正文時就會多心:

u 本章開頭講過,如果不主動編寫拷貝構造函數和賦值函數,編譯器將以“位拷貝”的方式自動生成缺省的函數。倘若類中含有指針變量,那麼這兩個缺省的函數就隱含了錯誤。以類String的兩個對象a,b為例,假設a.m_data的內容為“hello”,b.m_data的內容為“world”。

現將a賦給b,缺省賦值函數的“位拷貝”意味著執行b.m_data = a.m_data。這將造成三個錯誤:一是b.m_data原有的內存沒被釋放,造成內存洩露;二是b.m_data和a.m_data指向同一塊內存,a或b任何一方變動都會影響另一方;三是在對象被析構時,m_data被釋放了兩次。

u 拷貝構造函數和賦值函數非常容易混淆,常導致錯寫、錯用。拷貝構造函數是在對象被創建時調用的,而賦值函數只能被已經存在了的對象調用。以下程序中,第三個語句和第四個語句很相似,你分得清楚哪個調用了拷貝構造函數,哪個調用了賦值函數嗎?

String a(“hello”);

String b(“world”);

String c = a; // 調用了拷貝構造函數,最好寫成 c(a);

c = b; // 調用了賦值函數

本例中第三個語句的風格較差,宜改寫成String c(a) 以區別於第四個語句。

9.6 示例:類String的拷貝構造函數與賦值函數
// 拷貝構造函數

String::String(const String &other)

{

// 允許操作other的私有成員m_data

int length = strlen(other.m_data);

m_data = new char[length+1];

strcpy(m_data, other.m_data);

}

// 賦值函數

String & String::operate =(const String &other)

{

// (1) 檢查自賦值

if(this == &other)

return *this;

// (2) 釋放原有的內存資源

delete [] m_data;

// (3)分配新的內存資源,並復制內容

int length = strlen(other.m_data);

m_data = new char[length+1];

strcpy(m_data, other.m_data);

// (4)返回本對象的引用

return *this;

}

類String拷貝構造函數與普通構造函數(參見9.4節)的區別是:在函數入口處無需與NULL進行比較,這是因為“引用”不可能是NULL,而“指針”可以為NULL。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved