<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
今天和大家分享一下C++中在建立類的時候編譯器會提供給一個類至少三個函數,分別是預設建構函式,解構函式,拷貝建構函式。
我們在建立好類的物件之後,首先對它的每一個成員屬性賦值之後再對它們進行輸出操作,如果不賦值就輸出,這些值就會是垃圾值。而為了程式碼的簡介,一次性為所有成員屬性初始化,C++的類別提供了這樣的一個函數—建構函式。
1)建構函式,沒有返回值也不寫void
2) 函數名稱與類名相同
3)建構函式可以有引數,因此可以發生過載
4)程式在呼叫物件時候會自動呼叫構造,無須手動呼叫,而且只會呼叫一次
解構函式的作用與建構函式相反,一般是執行物件的清理工作,當物件的生命週期結束的時候,會自動的呼叫。解構函式的作用並不是刪除物件,在物件復原它所佔用的記憶體之前,做一些清理的工作。清理之後,這部分記憶體就可以被系統回收再利用了。在設計這個類的時候,系統也會預設的提供一個解構函式。在物件的生命週期結束的時候,程式就會自動執行解構函式來完成這些工作。同建構函式,使用者自己定義,系統自動呼叫。
1)解構函式,沒有返回值也不寫void
2) 函數名稱與類名相同,在名稱前加上符號 ~
3)解構函式不可以有引數,因此不可以發生過載
4) 程式在物件銷燬前會自動呼叫解構,無須手動呼叫,而且只會呼叫一次
程式碼演示:
class Person { public: //建構函式 Person() { cout << "Person的建構函式呼叫" << endl; } //解構函式 ~Person() { cout << "Person的解構函式呼叫" << endl; } }; void test01() { Person p; } int main() { test01(); system("pause"); return 0; }
按引數分為: 有參構造和無參構造
按型別分為: 普通構造和拷貝構造
括號法
顯示法
隱式轉換法
//1、建構函式分類 // 按照引數分類分為 有參和無參構造 無參又稱為預設建構函式 // 按照型別分類分為 普通構造和拷貝構造 class Person { public: //無參(預設)建構函式 Person() { cout << "無參建構函式!" << endl; } //有參建構函式 Person(int a) { age = a; cout << "有參建構函式!" << endl; } //拷貝建構函式 Person(const Person& p) { age = p.age; cout << "拷貝建構函式!" << endl; } //解構函式 ~Person() { cout << "解構函式!" << endl; } public: int age; }; //2、建構函式的呼叫 //呼叫無參建構函式 void test01() { Person p; //呼叫無參建構函式 } //呼叫有參的建構函式 void test02() { //2.1 括號法,常用 Person p1(10); //注意1:呼叫無參建構函式不能加括號,如果加了編譯器認為這是一個函數宣告 //Person p2(); //2.2 顯式法 Person p2 = Person(10); Person p3 = Person(p2); //Person(10)單獨寫就是匿名物件 當前行結束之後,馬上解構 //2.3 隱式轉換法 Person p4 = 10; // Person p4 = Person(10); Person p5 = p4; // Person p5 = Person(p4); //注意2:不能利用 拷貝建構函式 初始化匿名物件 編譯器認為是物件宣告 //Person p5(p4); } int main() { test01(); //test02(); system("pause"); return 0; }
C++中拷貝建構函式呼叫時機通常有三種情況
1.使用一個已經建立完畢的物件來初始化一個新物件
2.值傳遞的方式給函數引數傳值
3.以值方式返回區域性物件
class Person { public: Person() { cout << "無參建構函式!" << endl; mAge = 0; } Person(int age) { cout << "有參建構函式!" << endl; mAge = age; } Person(const Person& p) { cout << "拷貝建構函式!" << endl; mAge = p.mAge; } //解構函式在釋放記憶體之前呼叫 ~Person() { cout << "解構函式!" << endl; } public: int mAge; }; //1. 使用一個已經建立完畢的物件來初始化一個新物件 void test01() { Person man(100); //p物件已經建立完畢 Person newman(man); //呼叫拷貝建構函式 Person newman2 = man; //拷貝構造 //Person newman3; //newman3 = man; //不是呼叫拷貝建構函式,賦值操作 } //2. 值傳遞的方式給函數引數傳值 //相當於Person p1 = p; void doWork(Person p1) {} void test02() { Person p; //無參建構函式 doWork(p); } //3. 以值方式返回區域性物件 Person doWork2() { Person p1; cout << (int *)&p1 << endl; return p1; } void test03() { Person p = doWork2(); cout << (int *)&p << endl; } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
預設情況下,c++編譯器至少給一個類新增3個函數
1.預設建構函式(無參,函數體為空)
2.預設解構函式(無參,函數體為空)
3.預設拷貝建構函式,對屬性進行值拷貝
建構函式呼叫規則如下:
如果使用者定義有參建構函式,c++不在提供預設無參構造,但是會提供預設拷貝構造
如果使用者定義拷貝建構函式,c++不會再提供其他建構函式
class Person { public: //無參(預設)建構函式 Person() { cout << "無參建構函式!" << endl; } //有參建構函式 Person(int a) { age = a; cout << "有參建構函式!" << endl; } //拷貝建構函式 Person(const Person& p) { age = p.age; cout << "拷貝建構函式!" << endl; } //解構函式 ~Person() { cout << "解構函式!" << endl; } public: int age; }; void test01() { Person p1(18); //如果不寫拷貝構造,編譯器會自動新增拷貝構造,並且做淺拷貝操作 Person p2(p1); cout << "p2的年齡為: " << p2.age << endl; } void test02() { //如果使用者提供有參構造,編譯器不會提供預設構造,會提供拷貝構造 Person p1; //此時如果使用者自己沒有提供預設構造,會出錯 Person p2(10); //使用者提供的有參 Person p3(p2); //此時如果使用者沒有提供拷貝構造,編譯器會提供 //如果使用者提供拷貝構造,編譯器不會提供其他建構函式 Person p4; //此時如果使用者自己沒有提供預設構造,會出錯 Person p5(10); //此時如果使用者自己沒有提供有參,會出錯 Person p6(p5); //使用者自己提供拷貝構造 } int main() { test01(); system("pause"); return 0; }
淺拷貝:簡單的賦值拷貝操作
深拷貝:在堆區重新申請空間,進行拷貝操作
範例:
class Person { public: //無參(預設)建構函式 Person() { cout << "無參建構函式!" << endl; } //有參建構函式 Person(int age ,int height) { cout << "有參建構函式!" << endl; m_age = age; m_height = new int(height); cout << "拷貝建構函式!" << endl; //如果不利用深拷貝在堆區建立新記憶體,會導致淺拷貝帶來的重複釋放堆區問題 m_age = p.m_age; m_height = new int(*p.m_height) } //拷貝建構函式 Person(const Person& p) { ; } //解構函式 ~Person() { cout << "解構函式!" << endl; if (m_height != NULL) { delete m_height; } } public: int m_age; int* m_height; }; void test01() { Person p1(18, 180); Person p2(p1); cout << "p1的年齡: " << p1.m_age << " 身高: " << *p1.m_height << endl; cout << "p2的年齡: " << p2.m_age << " 身高: " << *p2.m_height << endl; } int main() { test01(); system("pause"); return 0; }
如果屬性有在堆區開闢的,一定要自己提供拷貝建構函式,防止淺拷貝帶來的問題
到此這篇關於C++類別中三大函數(構造、解構和拷貝)的文章就介紹到這了,更多相關C++類別的三大函數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45