首頁 > 軟體

C++類別與物件的詳細說明2

2022-02-17 19:01:10

類的預設成員函數

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

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

建構函式

概念

建構函式的作用即為初始化,相當於平時我們自己寫的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取地址操作符過載

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

總結

篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容! 


IT145.com E-mail:sddin#qq.com