介紹類的6個成員函數之前,我們先來看一下this指針
this指針
this 指針是成員函數里面的一個隱藏指針,指向了調用該函數的對象本身。
this指針特性:
(1)this指針的類型為:類類型* const
(2)this指針並不是對象本身的一部分,不影響sizeof結果
(3)this指針的作用域在類“成員函數”內部
(4)this指針是”類成員函數”的第一個默認隱含參數,編譯器自動維護傳遞,類編寫者不能顯式傳遞
(5)只有在類的非靜態成員函數中才可以使用this指針,其它任何函數都不可以
(6)this指針不能在初始化列表中使用
(7)當通過this指針訪問數據成員時,this指針不能為空
class Test { public: void FunTest() { cout << "FunTest():" << this << endl; //若不進行注釋程序會編譯錯誤,this指針為空,不能使用this指針來訪問數據成員 /*cout << this->_a << endl;*/ } private: int _a; }; int main() { Test* pt = NULL; pt->FunTest(); return 0; }
this指針是使用__thiscall調用約定的
(1)__thiscall只能夠用在類的成員函數上
(2) 參數從右向左壓棧
(3)如果參數個數確定,this指針通過ecx傳遞給被調用者;如果參數不確定(_cdecl),this指針在所有參數被壓棧后壓入堆棧
(4)對參數個數不定的,調用者清理堆棧,否則函數自己清理堆棧
類的6個默認的成員函數
構造函數:
(1)概念:構造函數是一個特殊的成員函數,名字和類名相同,無返回值類型,創建類對象時由編譯器自動調用,在對象的生命周期內只調用一次,保證每個數據成員都有一個合適的初始值
class Date { public: //初始化列表 Date(int year,int month,int day) :_year(year),_month(month),_day(day) { cout << "Date(int):" << this << endl; } private: int _year; int _month; int _day; }; int main() { Date d(2018, 6, 14); return 0; }
(2)特性:1)函數名與類名相同 ,沒有返回值 2) 新對象被創建時,由編譯器自動調用,且在對象的聲明周期內僅調用 一次 3)構造函數可以重載,實參決定了調用哪個構造函數 4)無參構造函數和帶有缺省值的構造函數都認為是缺省的構造函數,並 且缺省的構造函數只能有一個 5)有初始化列表6) 如果沒有顯式定義時,編譯器會合成一個默認的構造函數7) 構造函數不能用const修飾8)構造函數不能為虛函數
編譯器在什么時候合成默認構造函數?
1)有一個A類,A類中包含缺省的構造函數
2)有一個B類,包含了A類的對象,並且B類沒有顯式定義自己的構造函數
在這種情況下系統必須為B類合成默認構造函數,目的就是為了構造B對象中包含的A對象
如下:
class Time { public: Time(int hour=8,int minute=2,int second=45) :_hour(hour),_minute(minute),_second(second) {} private: int _hour; int _minute; int _second; }; class Date { private: int _year; int _month; int _day; Time _t; }; int main() { Date d;//會調用系統合成的構造函數 return 0; }
(3)對象初始化
初始化列表:以一個冒號開始,接着是一個以逗號分隔的數據成員列表, 每個”成員變量”后面跟一個放在括號中的初始值或表達式
注意:
1)每個成員在初始化列表中只能出現一次
因為初始化的時候需要划分空間,所以只能出現一次
2)初始化列表僅用於初始化類的數據成員,並不指定這些數據成員的初始化順序,數據成員在類中定義順序就是在參數列表中的初始化順序,盡量避免使用成員初始化成員,成員的初始化順序好和成員的定義 順序保持一致
3)類中包含以下成員,一定要放在初始化列表位置進行初始化:引用成員變量 const成員變量 類類型成員(該類有非缺省的構造函數)
類中包含類類型成員一定要放在初始化列表位置進行初始化:即A類中有非缺省的構造函數,B類中有構造函數,數據成員包含A類對象。
(4)構造函數作用
1)構造&初始化對象
2)類型轉換 對於單個參數構造函數,可以將其接受參數轉化成類類型對象。用 explicit修飾構造函數,抑制由構造函數定義的隱式轉換,explicit 關鍵字類內部的構建聲明上,在類的定義體外部的定義上不再重復,如:
class Date { public: //構造函數用explicit修飾可以避免類型轉換問題 Date(int year) :_year(year) { cout << "Date(int)" << this << endl; } private: int _year; int _month; int _day; }; int main() { Date d1(2018); d1 = 2019;//用2019來構造一個臨時對象,賦給d1 return 0; }
拷貝構造函數
class Date { public: Date(int year,int month,int day) :_year(year),_month(month),_day(day) { cout << "Date(int):" << this << endl; }; //拷貝構造函數 Date(const Date& d) :_year(d._year) ,_month(d._month) ,_day(d._day) { cout << "Date(const Date&):" << this << endl; }; private: int _year; int _month; int _day; }; int main() { Date d1(2018, 6, 14); Date d2(d1); return 0; }
(1)概念
只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾),這 樣的構造函數稱為拷貝構造函數。拷貝構造函數是特殊的構造函數,創建 對象時使用已存在的同類對象來進行初始化,由編譯器自動調用
(2)特征
1)是構造函數的重載,構造函數的性質拷貝構造函數均滿足
2)參數必須使用類類型對象引用傳遞(為什么?)
若用值傳遞傳參時,就會調用拷貝構造函數來構造臨時變量,形成遞歸
3)如果沒有顯式定義,系統會自動合成一個默認的拷貝構造函數。默認 的拷貝構造函數會依次拷貝類的數據成員完成初始化
析構函數
(1)概念
析構函數:與構造函數功能相反,在對象被銷毀時,由編譯器自動調用,完成類 的一些資源清理和汕尾工作
(2)特性
1)析構函數在類名(即構造函數名)加上字符~
2)析構函數無參數無返回值
3) 一個類有且只有一個析構函數。若未顯示定義,系統會自動生成缺省的析構函數
4)對象生命周期結束時,C++編譯系統系統自動調用析構函數
注意:析構函數體內並不是刪除對象,而是做一些清理工作
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。