1.構造函數:
>構造函數是一個特殊的、與類同名的成員函數,用於給每個成員設置適當的初始值。
>構造函數不能有返回值,函數名與類名相同。
>缺省構造函數時,系統將自動調用該缺省構造函數初始化對象,缺省構造函數會將所有數據成員都初始化為零或 空。缺省構造函數是不帶參數的構造函數。
>創建一個對象時,系統自動調用構造函數。
構造函數的特點:
1.構造函數可以重載,傳入什麼實參決定調用不同版本的構造函數。
2.構造函數不能聲明為const 、也不能聲明為virtual;(析構函數可以)
3.一個類如果自定義了一個構造函數,編譯器就不會生成默認構造函數。
4.只有構造函數才有類似初始化列表的形式來初始化成員變量(特別是const成員變量只能在初始化列表中初始化)
例子:
#include#include class Person { public: Person();//默認的構造函數 Person(int n, const string &str);//構造函數的重載 private: int age; string *name; };
2.拷貝構造
先介紹一下深拷貝與淺拷貝:
>淺拷貝: 指的是在對象復制時,只對對象中的數據成員進行簡單的賦值;默認拷貝構造函數執行的也是淺拷貝。 大多情況下“淺拷貝”已經能很好地工作了,但是一旦對象存在了動態成員,那麼淺拷貝就會出問題了。
>深拷貝:當類的成員變量有指針類型時,拷貝對象時應該為指針變量重新分配好空間,避免淺拷貝中只拷貝指針的
值,使得兩個指針指向同一塊內存空間。
淺拷貝缺陷例子:
#include#include using namespace std; class Person { public: Person(); Person(int n, const string &str);//構造函數重載 ~Person(); private: int age; string *name; }; Person::Person():age(0), name(NULL)//構造函數初始化列表,定義時不必寫! { cout << "Default Person" << endl; } Person::Person(int n, const string &str):age(n), name(new string(str)) { cout << "Init Person" << endl; } Person::~Person() { if(name) { cout << "~Person " << "name: " << *name << " age: " << age << endl; } delete name; } int main() { Person p1(10, string("SCOTT")); Person p2 = p1; return 0; }
運行結果:
Init Person
~Person name: SCOTT age: 10
Segmentation fault (core dumped)
程序崩潰原因:
p2由p1初始化而得到,由於我們沒有自定義拷貝構造函數,所以調用的是默認的拷貝構造函數,屬於淺拷貝,只對name的值進行了拷貝;p1與p2中的name指針指向同一個new空間,最後調用析構函數時,會造成兩次delete而出現段錯誤。
如下圖所示:
解決方法:自定義拷貝構造函數! 達到深拷貝的效果
深拷貝例子:<喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">#include 運行結果: Init Person ~Person name: SCOTT age: 10 ~Person name: SCOTT age: 10
沒有出現段錯誤,由此可見,上述解決方案可行。