C++入門淺談之類和對象
一、面向過程vs面向?qū)ο?/h2>
C語言面向過程,關(guān)注的是過程,分析出求解問題的步驟,通過函數(shù)調(diào)用逐步解決問題
C++是基于面向?qū)ο螅P(guān)注的是對象,將一件事情拆分成不同的對象,靠對象之間的交互完成,C++不是純面向?qū)ο蟮恼Z言,C++既有面向過程,也有面向?qū)ο罂梢曰旌暇幊?。C語言面向過程,數(shù)據(jù)和方法是分離的。CPP面向?qū)ο?,?shù)據(jù)和方法是封裝在一起的,如struct里即可用存數(shù)據(jù)也可以調(diào)用方法(函數(shù))
struct ListNodeCPP{ int val; ListNodeCPP* next; }; int main(){ //struct ListNodeCPP n1; 就不需要這樣調(diào)用了 ListNodeCPP n1; }
所以這里的struct已經(jīng)不僅僅是結(jié)構(gòu)體,在cpp中已經(jīng)升級成了類名
二、類的限定符及封裝
類包括成員變量和成員函數(shù)
下圖為類的訪問限定符及封裝
Warning:
在class中,如果不寫訪問限定符默認(rèn)是私有
在struct中,如果不寫訪問限定符默認(rèn)是公有
class類中的private里的成員變量前面都會加個下劃線因為在函數(shù)復(fù)制時更加容易區(qū)分
面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài)
本節(jié)只介紹封裝,封裝是將數(shù)據(jù)和操作數(shù)據(jù)進(jìn)行有機(jī)結(jié)合,隱藏對象的屬性和實現(xiàn)細(xì)節(jié),僅對外公開接口來和對象進(jìn)行交互
封裝本質(zhì)上是一種管理,類似兵馬俑,如果什么都不管兵馬俑就會被隨意破壞那么我們首先建一座房子把兵馬俑給封裝起來。
但是我們不能全部封裝起來,所以開放了搜票通道,買了門票的可以進(jìn)去參觀。類也是一樣,我們使用類數(shù)據(jù)和方法都封裝一下。
不想給別人看的,我們使用proteced/private把成員封裝起來。開放一些共有的成員函數(shù)對成員合理的訪問。所以封裝本質(zhì)上是一種管理
Warning:在類中private域聲明的變量僅僅是聲明,但是沒有開空間,我們只有在實例化的時候才算是定義,public域下亦是如此。
總結(jié)就是定義是開空間,在實例化后才是定義,class里只是聲明
三、類的實例化
用類類型創(chuàng)建對象的過程,稱為類的實例化
1.類限定了有哪些成員,定義出的一個類并沒有分實際的內(nèi)存空間來存儲它
2.一個類可以實例化多個對象,實例化出的對象占用實際的物理空間,存儲類成員變量
3.類實例化出對象就像現(xiàn)實中造車,類是車的設(shè)計圖,只負(fù)責(zé)設(shè)計需要什么東西,但并沒有實體,同樣類也只是個設(shè)計,實例化出的對象才能實際存儲數(shù)據(jù),占用物理空間
上圖這個只算class里變量的大小,因此只保存成員變量,成員函數(shù)存放在公共的代碼段
那么定義一個空類呢?
class Cpp{}
那么sizeof的大小為1 , 而不是0,因為如果一個類沒有成員,那么他的對象需要給1byte進(jìn)行占位
標(biāo)識對象存在,這1個byte不存儲有效數(shù)據(jù)
四、this指針
C++編譯器給每個非靜態(tài)成員函數(shù)增加了一個隱藏的指針參數(shù),讓該指針指向當(dāng)前對象(函數(shù)運(yùn)行時調(diào)用該函數(shù)的對象),在函數(shù)體中,所以成員變量的操作都是通過該指針去訪問
下面的代碼為編譯器處理成員函數(shù)的this指針,也可以不寫那么編譯器會自動傳隱含的this指針
class Date{ public: void date(int year, int month, int day){ this->_year = year; this->_month = month; this->_day = day; } void Print(){ cout << _year << "/" << _month << "/" << _day <<endl; } private: int _year; int _month; int _day; };
this指針特性:
1.this指針的類型:類類型* const
2.只能在成員函數(shù)的內(nèi)部使用
3.this指針本質(zhì)上是一個成員函數(shù)的形參,是對象調(diào)用成員函數(shù)時,將對象地址作為實參傳遞給this形參。所以對象中不存儲this指針
4.this指針是成員函數(shù)第一個隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳第,不需要用戶傳遞
五、默認(rèn)成員函數(shù)
上圖為默認(rèn)的成員函數(shù),那么如果定義了一個class而里面什么都不寫的話,仍會自動生成上面6個默認(rèn)成員函數(shù)
1. 構(gòu)造函數(shù)
我們首先要介紹的就是構(gòu)造函數(shù),因為一般在C語言中一般會先進(jìn)行初始化,在C++中一般寫在類里,這樣我們在實例化的過程中就可以省去很多時間,而且避免了忘記初始化的風(fēng)險。
構(gòu)造函數(shù)特征:
1.函數(shù)名與類名相同
2.無返回值
3.對象實例化時編譯器自動調(diào)用對應(yīng)的構(gòu)造函數(shù)
4.構(gòu)造函數(shù)可以重載
所以構(gòu)造函數(shù)實際上能夠做到我們對象一定義出來就初始化了
class Date{ public: Date(){ _year = 0; _month = 0; _day = 0; } //帶參構(gòu)造函數(shù) Date(int year, int month, int day){ _year = year; _month = month; _day = day; } //全缺省,注意默認(rèn)構(gòu)造函數(shù)只能有一個,所以只能選一種我們推薦用全缺省方式的構(gòu)造函數(shù) Date(int year=2022, int month = 2, int day = 20){ _year = year; _month = month; _day = day; } void date(int year, int month, int day){ this->_year = year; this->_month = month; this->_day = day; } void Print(){ cout << _year << "/" << _month << "/" << _day <<endl; } private: int _year; int _month; int _day; }; int main(){ Date day1; //注意這種是調(diào)用無參構(gòu)造函數(shù) Date day2(2021,10,19); //帶參構(gòu)造函數(shù) Date day3(); //函數(shù)聲明,返回一個日期類型的對象 }
Warning:
如果用戶顯示定義了構(gòu)造函數(shù),編譯器將不再生成內(nèi)置類型不會初始化 ,如int/char/double/指針等自定義類型會調(diào)用他的構(gòu)造函數(shù)初始化,如struct/class/union
2. 析構(gòu)函數(shù)
對象在銷毀時會自動調(diào)用析構(gòu)函數(shù),完成類的一些資源清理工作
析構(gòu)特征:
1.在類名的前面加上字符: ~
2.無參數(shù)無返回值
3.一個類有且只有一個析構(gòu)函數(shù)。如果沒有定義系統(tǒng)將自動生成默認(rèn)的
4.對象生命周期結(jié)束時,C++編譯系統(tǒng)自動調(diào)用析構(gòu)函數(shù)
class SeqList { public : SeqList (int capacity = 10) { _pData = (DataType*)malloc(capacity * sizeof(DataType)); assert(_pData); _size = 0; _capacity = capacity; } ~SeqList() { if (_pData) { free(_pData ); // 釋放堆上的空間 _pData = NULL; // 將指針置為空 _capacity = 0; _size = 0; } } private : int* _pData ; size_t _size; size_t _capacity; };
3. 拷貝函數(shù)
顧名思義就是拷貝一個一摸一樣的對象
特征:
1.是構(gòu)造函數(shù)的一個重載形式
2.參數(shù)只有一個且必須使用引用傳參,使用傳值方式會引發(fā)無窮遞歸調(diào)用
下面就會引發(fā)無窮遞歸,解決辦法就是在Date類型后面加一個引用,這里就變成了用別名區(qū)分
3. 如果未定義,系統(tǒng)生成默認(rèn)的 拷貝構(gòu)造函數(shù)。默認(rèn)的拷貝構(gòu)造函數(shù)對象按內(nèi)存存儲按字節(jié)序完成拷貝,這種拷貝成為淺拷貝
4. 賦值運(yùn)算符重載
我們先了解一個概念叫運(yùn)算符重載,具有其返回值類型,函數(shù)名以及參數(shù)列表
關(guān)鍵字:operator后面接需要重載的運(yùn)算符符號
Warning:
1.作為類成員的重載函數(shù)時,其形參看起來比操作數(shù)數(shù)目少一個成員函數(shù),實際上并不是這樣子的,操作符有一個默認(rèn)形參this,限定為第一個形參
2.以下符號不能重載:.* , :: . sizeof , ?: . .
3.我們定義operation一般在public里面而不是全局,因為如果我們修改不了private里面的成員變量,就保證不了封裝性
特征:
1. 參數(shù)類型
2.返回值
3.檢查是否自己給自己賦值
4. 返回*this
5. 一個類如果沒有顯示定義賦值運(yùn)算符重載,編譯器也會生成一個,完成對象按字節(jié)序的值拷貝
下面就簡單實現(xiàn)了日期增加N天的運(yùn)算符賦值
//Date day(2021,10,10); //day += 20; Date& Date::operator+=(int day){ if(day<0){ return *this -= -day; }else{ _day += day; //如果日期不合法,進(jìn)位 while(_day > GetMonthDay(_year, _month)){ _day -= GetMonthDay(_year, _month); ++_month; if(_month == 13){ ++_year; _month = 1; } } } return *this; }
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++ 虛函數(shù)和純虛函數(shù)的區(qū)別分析
這篇文章主要介紹了C++ 虛函數(shù)和純虛函數(shù)的區(qū)別,幫助大家更好的理解和學(xué)習(xí)c++的相關(guān)知識,感興趣的朋友可以了解下2020-10-10linux c++ 服務(wù)器端開發(fā)面試必看書籍整理
這篇文章主要介紹了linux c++ 服務(wù)器端開發(fā)面試必看書籍整理,需要的朋友可以參考下2020-02-02C++運(yùn)行時類型識別與轉(zhuǎn)換實現(xiàn)方法
運(yùn)行時類型識別可能被認(rèn)為是C++中一個”次要“的特征,當(dāng)程序員在編程過程中陷入非常困難的境地時,實用主義將會幫助他走出困境2022-10-10