網站首頁 編程語言 正文
一、類的默認成員函數
二、構造函數Date(形參列表)
構造函數主要完成初始化對象,相當于C語言階段寫的Init函數。
默認構造函數:無參的構造函數或全缺省的構造函數,二者只能存在一個,同時存在類中,調用時會出現二義性。
1、構造函數的函數名和返回值
構造函數的函數名和類名相同且無返回值
2、構造函數的調用
對象實例化時,編譯器自動調用對應的構造函數且只調用一次
3、構造函數的重載
構造函數可以重載(多種初始化方式)注意:雖然全缺省和無參的構造函數構成重載,但是調用時存在二義性。
class Date
{
public:
//構造函數的重載
Date()
{
}
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;//創建并通過無參構造函數初始化對象時,無需加括號,不然變成了函數聲明
Date d2(2022,9,23);
return 0;
}
4、系統生成的默認構造函數
如果我們在類中不寫構造函數,C++編譯器會在類中幫我們生成一個無參的構造函數。我們寫了構造函數,那么系統將不會生成。
我們構造對象并調用構造函數時,初始化的數據是隨機值:
5、系統生成的默認構造函數的作用
系統生成默認構造函數對內置類型不處理,對自定義類型調用他的構造函數。
注意:下方代碼中,Date類中的內置類型將會調用Date類中的構造函數;Date類中的Time _t將會調用Time類中的構造函數。
6、可以在內置類型的成員變量的聲明中給缺省值
C++11中針對內置類型不處理初始化為隨機值的問題,打了補丁:內置類型成員變量在類中聲明可以給默認值,甚至可以給動態開辟的缺省值,缺點是不能判斷空間是否開辟成功。
注意這里的默認值是缺省值,不是初始化。初始化是要等對象調用時才叫初始化。
class Date
{
private:
int _year=1;
int _month=2;
int _day=3;
int* arr = (int*)malloc(sizeof(int) * 5);
};
這個特性只能用于解決默認構造函數初始化為隨機值的問題。這個特性不能解決對象的多種初始化方式(這也是構造函數支持重載的原因),構造函數該寫還是得自己寫。
7、初始化列表初始化
- 1、對象的每個成員變量是在初始化列表部分進行初始化,而函數體內的行為是對成員函數賦初值。
- 2、如果沒有在初始化列表里顯示初始化某個成員函數,對于內置類型,有缺省值用缺省值,無缺省值初始化為隨機值;對于自定義類型將會調用它的默認構造函數,沒有找到默認構造就會報錯。
- 3、引用、const、無默認構造函數的自定義類型必須通過初始化列表初始化。
- 4、成員變量在類中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后次序無關。
Date(int year=1,int month=1,int day=1)//缺省值
:_year(year)//成員變量的定義
,_month(month)
,_day(day)
{}//成員變量的賦初值
總結:盡量使用使用初始化列表進行初始化,在類中盡量提供默認構造函數(最好是全缺省的默認構造函數)
8、單參數構造(C++98)、多參數構造(C++11)
class Date
{
public:
Date(int year=1,int month=1,int day=1)
:_year(year)
,_month(month)
,_day(day)
{}
private:
int _year;
int _month;
int _day;
};
int main()
{
//單參數的構造,構造+拷貝,編譯器直接優化為構造C++98
Date d1 = 2022;
//臨時對象具有常性,構造+拷貝,編譯器不會優化
const Date& d2 = 2023;
//多參數的構造C++11
Date d3 = { 2022,10,16 };
return 0;
}
- 1、在構造時,支持等號加參數的構造形式,實際上發生的是隱式類型轉換。2022由int類型隱式類型轉換為Date型的臨時對象,該臨時對象再將它的值拷貝構造給d1。
- 2、2023會隱式類型轉換為Date類型的臨時對象,具有常屬性。d2是這個臨時對象的引用,所以需要加上const。這里發生構造+拷貝構造,涉及臨時對象的引用,所以編譯器并不會發生優化。
- 3、可以使用explicit關鍵字修飾構造函數,會禁止隱式類型轉換。
三、析構函數~Date()
析構函數:與構造函數功能相反,析構函數不是完成對對象本身的銷毀,局部對象銷毀工作是由編譯器完成的。而對象在銷毀時會自動調用析構函數,完成對象中資源的清理工作。資源包括動態開辟的空間,文件的關閉等。相當于C語言階段寫的destroy函數。
1、析構函數的函數名、參數和返回值
析構函數的函數名是類名前加~,無參無返回值類型。
2、析構函數的特點
一個類只能有一個析構函數。若未顯式定義,系統會自動生成默認的析構函數。注意:析構函數不能重載
對象生命周期結束時,C++編譯系統系統自動調用析構函數
3、編譯器生成的默認析構函數
對于編譯器生成的默認析構函數,對自定義類型調用他的析構函數。對于內置類型,沒有需要處理資源。
注意:Date類中的內置類型會調用Date類中的析構函數;Date類中的自定義類型Time _t會調用Time的析構函數。
四、拷貝構造Date(const Date& d)
1、拷貝構造函數是構造函數的重載
拷貝構造函數:只有單個形參,該形參是對本類類型對象的引用(一般常用const修飾),在用已存在的類類型對象創建新對象時由編譯器自動調用。
拷貝構造函數的函數名和構造函數相同,無返回值,在參數上和構造函數構成重載。
2、拷貝構造函數的參數
拷貝構造函數的參數只有一個并且是類類型對象的引用。如果使用傳值傳參的方式進行拷貝構造,在傳值的過程中實參需要拷貝一份數據給形參,這個過程需要調用拷貝構造。形成層層傳值引發對象的拷貝的遞歸(有遞無歸)調用。
3、若未顯式定義,編譯器會生成默認的拷貝構造函數
默認的構造函數對于內置類型按照字節拷貝。對于自定義類型則調用它的拷貝構造函數。
4、拷貝構造函數的深淺拷貝
通過默認的拷貝構造函數構造的對象,按字節完成拷貝。這種拷貝被稱為淺拷貝(值拷貝)。
int main()
{
Date d1(2022,9,24);
Date d2(d1);
return 0;
}
對于內置類型,使用淺拷貝即可,系統默認生成的就可以做到,所以我們不用動手寫拷貝構造函數。注意這里有d1,d2兩個對象,當main函數生命周期結束時,這兩個對象均會發生一次析構,d2先析構,d1后析構。(后定義的先銷毀,類似棧的后進先出原則)
但是淺拷貝對于占用“資源”的成員變量時(例如成員變量中有動態開辟或fopen的資源),指針雖然復制了,但是所指向的內容卻沒有復制,析構時存在同一塊空間被釋放兩次的問題。需要進行深拷貝。深拷貝的拷貝構造函數必須自己手動實現。
class Stack
{
public:
Stack(int capacity=100)//構造函數
{
_capacity = capacity;
_top = 0;
_arr = (int*)malloc(sizeof(int) * 5);
if (_arr == nullptr)
{
perror("malloc fail");
exit(-1);
}
}
//Stack(const Stack& st)//淺拷貝,棧這個類不能用淺拷貝
//{
// _capacity = st._capacity;
// _top = st._top;
// _arr = st._arr;
//}
Stack(const Stack& st)//深拷貝
{
_capacity = st._capacity;
_top = st._top;
_arr = (int*)malloc(sizeof(int) * st._top);
if (_arr == nullptr)
{
perror("malloc fail");
exit(-1);
}
memcpy(_arr, st._arr,sizeof(int)*st._top);
}
~Stack()//析構函數
{
_capacity = 0;
_top = 0;
free(_arr);
_arr = nullptr;
}
private:
int* _arr;
int _top;
int _capacity;
};
棧這個類因為成員變量中有動態開辟的空間,所以要用深拷貝。
5、拷貝構造函數調用場景
- 1、使用已存在的對象創建新對象
- 2、函數參數類型為類的類型對象(傳值調用,實參拷貝給形參)
- 3、函數返回值類型為類的良心對象(傳值返回)
五、賦值運算符重載Date& operator=(const Date& d )
1、賦值運算符重載
只有賦值運算符是默認成員函數。
2、賦值運算符重載的注意事項
- 1、參數是const T&,傳引用可以減少一次拷貝構造。
- 2、返回值是*this的引用,引用返回,減少一次拷貝構造,有返回值是為了支持函數的鏈式訪問。
- 3、務必檢查下是否支持自己給自己賦值。
- 4、賦值運算符重載必須是類中的默認成員函數,不能寫在全局。
- 5、系統默認生成的賦值運算符重載會完成值拷貝。
六、取地址操作符重載和const取地址操作符重載
Date* operator&()
{
return this;
//return nullptr;
}
const Date* operator&()const
{
return this;
//return nullptr;
}
不用自己寫,除非想讓別人通過取地址操作符獲取到特定值(自己在重載函數內部寫)或屏蔽類地址。
原文鏈接:https://blog.csdn.net/gfdxx/article/details/127313617
相關推薦
- 2022-07-25 Oracle中的序列SEQUENCE詳解_oracle
- 2022-03-28 c語言for、while和do-while循環之間的區別_C 語言
- 2022-07-09 Android同步異步任務與多線程和Handler消息處理機制
- 2022-11-15 C語言自研定時器計劃任務語法詳解_C 語言
- 2022-12-10 Input系統之InputReader處理合成事件詳解_Android
- 2022-08-11 python中的多線程鎖lock=threading.Lock()使用方式_python
- 2022-04-15 C語言各種操作符透徹理解下篇_C 語言
- 2023-02-07 Pytorch中的廣播機制詳解(Broadcast)_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支