C++類與對象的詳細說明2

類的默認成員函數

每個類中,如果不主動實現默寫特定函數,類中也會自動去生成這些函數,它們就是默認成員函數。默認成員函數分為六種,它們是特殊的成員函數,如果我們不實現,編譯器會自己實現。

下面將對這些函數一 一進行介紹。

構造函數

概念

構造函數的作用即為初始化,相當於平時我們自己寫的Init函數,但在對象實例化時會自動調用,以保證實例化對象一定初始化。

特性

(1)函數名與類名相同

如日期類Date,其構造函數名也為Date

(2)無返回值

以日期類為例,其構造函數的聲明和定義可以寫成如下樣子:

class Date{public:Date(int year = 0, int month = 1, int day = 1);private:int _year;int _month;int _day;};class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1);
private:
	int _year;
	int _month;
	int _day;
};
Date::Date(int year, int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

(3)對象實例化時編譯器自動調用對應的構造函數

為瞭驗證這一點,我們創建一個對象,但不對其進行其它操作:

int main()
{  
	Date date1;
	return 0;
}

 通過調試可以發現對象date1已經被自動初始化瞭。

(4)構造函數可以重載

(5)如果類中沒有顯式定義構造函數,則C++編譯器會自動生成一個無參的默認構造函數,一旦用戶顯式定義,編譯器將不再自動生成。

(6)無參的構造函數和全缺省的構造函數都稱為默認構造函數,並且默認構造函數隻能有一個。

針對第五點,我們不免會發出疑問,編譯器自動生成的默認構造函數究竟幹瞭什麼呢?

首先,需要先瞭解C++把類型分為兩類:內置類型(基本類型)和自定義類型。

內置類型就是C語言自帶的類型,如int、char、double、指針、內置類型的數組;而自定義類型就是strucrt和class定義的類型。

編譯器默認生成的構造函數,對於成員變量中的內置類型不做初始化,對於自定義類型成員變量則會調用它的默認構造函數初始化,如果沒有默認構造函數則會報錯。

析構函數

概念

析構函數的功能是完成對象中資源的清理。虛構函數會在對象的生命周期到瞭之後調用。

特性

(1)析構函數名是在類名前加上字符~。

(2)無參數無返回值。

日期類析構函數的聲明可以寫成如下形式:

~Date();

(3)一個類有且隻有一個析構函數。若喂顯式定義,系統會自動生成默認的析構函數。

(4)對象生命周期結束時,C++編譯系統自動調用析構函數。 

對於編譯器自動生成的默認析構函數,與構造函數類似,對於內置類型成員變量不做處理;對於自定義類型成員變量會去調用它的構造函數。

拷貝構造函數

概念

拷貝構造函數用於使用同類型對象去初始化實例對象。

特征

(1)拷貝構造函數是構造函數的一個重載形式。

(2)拷貝構造函數的參數隻有一個且必須使用引用傳參,使用傳值的方式會引發無窮遞歸調用。

日期類拷貝構造函數的聲明需要寫成如下形式:

Date(Date& date);

為什麼必須采用引用傳參呢?引發無窮遞歸又是怎麼一回事呢?

不妨來思考一下,傳參實際上也是對內容進行臨時拷貝,將實參傳給形參本身就需要調用拷貝構造。由此一來,會導致不斷調用拷貝構造,造成無窮遞歸調用。

(3)若未顯式定義,系統會生成默認的拷貝構造函數瞭。

默認拷貝構造函數對於內置類型成員,會完成按字節序的拷貝(淺拷貝),如果需要深拷貝則需要自己寫拷貝構造函數;對於自定義類型成員,則會調用它的拷貝構造函數。

所謂按字節序拷貝指將內存中的內容照搬照抄,復制過來。在一些情況下就會出錯,如存放申請內存地址的指針,如果按字節序拷貝,會導致兩個對象中的成員變量指向同一塊空間,在析構時會導致同一塊空間釋放內存多次,引發錯誤。

賦值運算符重載

運算符重載

在談及賦值運算符重載前,必須先來講一講運算符重載。

我們知道,對於int類型,是可以進行加減乘除等運算的。但對於自定義類型,能否實現加減乘除運算呢?這就需要運用到運算符重載瞭。

運算符重載是具有特殊函數名的函數。函數名字為:operator操作符(參數列表)

註意:一些運算符不支持重載,即:.*、::、sizeof、?:、.

以Date類==運算符重載為例,需要將函數作為成員函數,以便於訪問成員變量:

class Date
{
public:
	Date(int year = 0, int month = 1, int day = 1);
	bool operator==(Date& date)const;
private:
	int _year;
	int _month;
	int _day;
};
bool Date::operator==(Date& date)const
{
	return _year == date._year
		&& _month == date._month
		&& _day == date._day;
}

賦值運算符重載

賦值運算符重載顧名思義,是對賦值運算符進行的重載,用於兩個已經存在的對象進行賦值拷貝。

賦值運算符重載有四個要點:

(1)參數類型

(2)返回值

(3)檢測是否自己給自己賦值

(4)返回*this,用於連續賦值

一個類如果沒有顯式定義賦值運算符重載,編譯器會自己生成一個,對於內置成員,完成按字節序拷貝;對於自定義成員變量,會調用它的賦值運算符重載。

取地址及const取地址操作符重載

這兩個運算符一般不需要重新定義,使用編譯器生成的重載即可,隻有特殊情況才需要重載,如不希望自己特定的內容被別人訪問時。

總結

篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容! 

推薦閱讀: