類中默認的函數
我們自己定義的類,或者C++標準裏默認提供的類,我們都可以看成是區別於基本數據類型(char,int,double等)的新類型,比如我們使用int類型時,一般會有如下的一些操作,如:
(1)int a;//定義一個變量
(2)int a = 10;//定義一個變量並進行初始化操作
(3)
int a(10);
int b = a;//定義一個變量,並對其進行初始化操作
(4)
void fun(int i){}
int a = 10;
fun(a);//定義一個變量並將其作為函數參數進行傳遞,函數參數的給值也是初始化操作
既然都是數據類型,那麽其操作也是大同小異的。在一個沒有任何成員函數的類,會有以下的默認函數(對於這些默認的函數,只要自己手動編寫了這些函數,那麽默認的就會被覆蓋):
class Test { public: Test() {}//默認構造函數 Test(const Test &t) {}//默認拷貝構造函數 Test &operator=(const Test &t) {}//默認“=”運算符重載函數 ~Test() {}//默認析構函數 };
(a)默認無參構造函數(只要是構造函數,都沒有返回值的)
作用是讓這個新的數據類型可以定義變量(對象),就像int a;
此時,我們不能完成成員變量的初始化,要想完成成員變量的初始化,我們可以自己寫一個構造函數,然後再初始化列表中進行成員變量的初始化(註意:初始化列表的執行順序是從上到下,即成員變量的聲明順序)
(b)默認拷貝構造函數
參數是當前類的一個常量引用
默認的拷貝構造是淺拷貝,當有成員變量時,淺拷貝時這樣的:
class Test { public: int m_a; public: Test() {} Test(const Test &t) { this->m_a = t.m_a; } Test &operator=(const Test &t) {} ~Test() {} };
對於這種類型的變量時沒問題的,但是當成員變量是其他類的指針變量時,那麽就會讓兩個指針變量指向同一塊空間,當我們用delete 指針變量時,就會刪除同一塊空間刪除兩次,這樣就會導致程序奔潰,所以這種情況,我們需要自己手動編寫拷貝構造函數,將那塊空間也拷貝一份,這樣程序就能正常運行了。
class Test{}; void fun(Test t); Test fun2(); Test t1; Test t2(t1);//調用默認的拷貝構造 Test t3 = t1;//調用默認的拷貝構造 這個和上面是一樣的,只是寫法不同 Test t4; fun(t1);//調用默認的拷貝構造 t4 = fun2();//調用默認的拷貝構造
(c)默認“=”運算符重載函數
class Test{}; Test t1; Test t2; t2 = t1;//調用默認“=”操作符重載函數
註意:默認拷貝構造函數和默認“=”操作符重載函數都會檢查對象是否初始化,比如:
class Test { public: int m_a; }; int main() { Test t1; Test t2; t2 = t1;//編譯失敗,使用了未初始化的局部變量"t1" Test t3 = t1;//編譯失敗,使用了未初始化的局部變量"t1" return 0; }
(d)析構函數
類中默認的函數