c++中類的預設四個成員函式介紹(建構函式+拷貝構造+解構函式+賦值運算子過載函式)
在C++中,類的6個預設的成員函式包括:
建構函式、解構函式、拷貝建構函式、賦值運算子過載函式、取地址操作符過載、const修飾的取地址操作符過載。
本文將主要介紹前四個成員函式:
一、建構函式
在c++程式中,物件的初始化時一個不可缺少且十分重要的問題,因此c++在類的設計中提供了建構函式。
建構函式,顧名思義,為物件分配空間,進行初始化,它是一種特殊的成員函式,具有以下特點:
- 1.函式名與類名相同。
- 2.無返回值。
- 3.構造物件的時候系統會自動呼叫建構函式。
- 4.可以過載。
- 5.可以在類中定義,也可以在類外定義。
- 6.如果類中沒有給出建構函式,編譯器會自動產生一個預設的建構函式,如果類中有建構函式,編譯器就不會產生預設建構函式。
- 7.全預設的建構函式和無參的建構函式只能有一個,否則呼叫的時候就會產生衝突。
- 8.沒有this指標。因為建構函式才是建立物件的,沒有建立物件就不會有物件的首地址。
建構函式,說來就是給成員變數進行初始化。而初始化卻有兩種方法:初始化列表、建構函式函式體內賦值。
舉例:以日期類來說明:
class Date
{
public:
Date()//無參建構函式
{
m_year = 2016;
m_month = 7;
m_day = 6;
}
Date(int year = 1900, int month = 1, int day = 1)//全預設的建構函式
{
m_year = year;
m_month = month;
m_day = day;
}
Date(int year, int month, int day) :m_year(year), m_month(month), m_day(day)
//初始化列表初始化成員變數
{
}
void print()
{
cout << m_year << "-" << m_month << "-" << m_day << endl;
}
private:
int m_year;
int m_month;
int m_day;
};
int main()
{
Date date(2017,6,28);
date.print();
system("pause");
return 0;
}
上邊這段程式碼只是為了解釋初始化列表初始化成員變數和在建構函式體內初始化,也解釋了無參建構函式和全預設的建構函式。宣告:由於上邊的程式碼同時給出無參和全預設的建構函式,產生呼叫衝突,編譯不通過。
既然有兩種初始化的方法,我們究竟該怎樣選擇呢??
儘量使用初始化列表,因為它更高效。
有些成員變數必須再初始化列表中初始化,比如:
1、常量成員變數。(常量建立時必須初始化,因為對於一個常量,我們給它賦值,是不對的)
2、引用型別成員變數。(引用建立時必須初始化)
3、沒有預設建構函式的類成員變數。(如果建構函式的引數列表中有一個類的物件,並且該物件的類裡沒有預設引數的建構函式時,要是不使用初始化列表,引數中會呼叫無參或者全預設的建構函式,而那個類中又沒有。)
二、解構函式
解構函式是一種特殊的成員函式,具有以下特點:
解構函式函式名是在類名加上字元~。
無引數無返回值(但有this指標)。
一個類有且只有一個解構函式,所以肯定不能過載。若未顯示定義,系統會自動生成預設的解構函式。
物件生命週期結束時,C++編譯系統系統自動呼叫解構函式。
注意解構函式體內並不是刪除物件,而是做一些清理工作。(比如我們在建構函式中動態開闢過一段空間,函式結束後需要釋放,而系統自動生成的解構函式才不管記憶體釋放呢,所以需要人為地寫出解構函式)
注意:物件生命週期結束後,後構造的物件先釋放。
三、拷貝建構函式
用已有的物件建立一個新的物件。仍然使用上邊的日期類舉例:
int main()
{
Date d1(2016,7,6);
Date d2(d1);
system("pause");
return 0;
}
上邊是用d1建立一個d2,系統會給出預設的拷貝建構函式,並且該函式的引數是一個常引用,我們想象為什麼必須是引用呢,如果不是又會發生什麼。
如果不是引用,形參是實參的一份臨時拷貝,由於兩者都是物件,此時就會呼叫自己的拷貝建構函式,陷入無限遞迴中…….
呼叫拷貝建構函式的3種情況:
當用類的一個物件去初始化該類的另一個物件時。
當函式的形參是類的物件,呼叫函式時進行形參和實參的結合時。
- 當函式的返回值是物件,函式執行完返回呼叫者時。(函式執行結束後,返回的物件會複製到一個無名物件中,然後返回的物件會消失,當呼叫語句執行完之後,無名物件就消失了)
呼叫拷貝建構函式的兩種方法:
1.代入法:Person p2(p1);
2.賦值法:Person p2 = p1;
四、賦值運算子過載函式
它是兩個已有物件一個給另一個賦值的過程。它不同於拷貝建構函式,拷貝建構函式是用已有物件給新生成的物件賦初值的過程。
預設的賦值運算子過載函式實現的資料成員的逐一賦值的方法是一種淺層拷貝。