C++:類中兩個易被忽略的默認函數
阿新 • • 發佈:2017-08-30
ont names namespace tor img c++編譯 style div 顯式
C++的自定義類中有六個默認的函數,即如果用戶沒有顯式定義這些函數時,C++編譯器會類中生成這些函數的默認形式。除了大家所熟知的構造函數、拷貝構造函數、賦值函數和析構函數外,C++為自定義類 還提供了兩個容易被人忽視的默認函數——取地址函數和對常對象的取地址函數。
一、取地址函數
在C++中可以通過取地址運算符&求得變量的地址,如:
1 int a=10; 2 cout<<"變量a的地址為:"<<&a<<endl;
那麽對於自定義類的對象是否可以通過取地址運算符&求得對象在內存中的地址呢?我們先來看個例子:
1 #include<iostream> 2#include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){ 7 cout<<"調用無參數的構造函數"<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){ 10 cout<<"調用有參數的構造函數"<<endl; 11 } 12 Student(const Student& stu){13 cout<<"調用拷貝構造函數"<<endl; 14 Name=stu.Name; 15 Age=stu.Age; 16 } 17 Student& operator=(const Student& stu){ 18 cout<<"調用賦值函數"<<endl; 19 if(this!=&stu){ 20 Name=stu.Name; 21 Age=stu.Age; 22 }23 return *this; 24 } 25 ~Student(){ 26 cout<<"調用析構函數"<<endl; 27 } 28 private: 29 string Name; 30 int Age; 31 }; 32 int main(){ 33 Student stu("Tomwenxing",23); 34 cout<<"對象stu的地址為:"<<&stu<<endl;//成功:運行對對象stu進行取地址操作 35 return 0; 36 }
由上面的例子可知,C++允許通過取地址運算符&求得對象在內存中的地址,而這個功能就是依靠類中的取地址函數實現的。和賦值函數相似,類中的取地址函數是通過對取地址運算符&進行重載來實現的,如果用戶在編寫類時沒有顯式地定義類的取地址函數,那麽C++編譯器將會在類中生成一個默認的取地址函數。
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){ 7 cout<<"調用無參數的構造函數"<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){ 10 cout<<"調用有參數的構造函數"<<endl; 11 } 12 Student(const Student& stu){ 13 cout<<"調用拷貝構造函數"<<endl; 14 Name=stu.Name; 15 Age=stu.Age; 16 } 17 Student& operator=(const Student& stu){ 18 cout<<"調用賦值函數"<<endl; 19 if(this!=&stu){ 20 Name=stu.Name; 21 Age=stu.Age; 22 } 23 return *this; 24 } 25 Student* operator&(){ //取地址函數 26 cout<<"調用取地址函數"<<endl; 27 return this; 28 } 29 ~Student(){ 30 cout<<"調用析構函數"<<endl; 31 } 32 private: 33 string Name; 34 int Age; 35 }; 36 int main(){ 37 Student stu("Tomwenxing",23); 38 cout<<"對象stu的地址為:"<<&stu<<endl;//成功:運行對對象stu進行取地址操作,該語句相當於stu.operator&(); 39 return 0; 40 }
二、對常對象的取地址函數
還是上面的例子,這次我們隊常對象進行取地址操作,看看會發生什麽:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){ 7 cout<<"調用無參數的構造函數"<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){ 10 cout<<"調用有參數的構造函數"<<endl; 11 } 12 Student(const Student& stu){ 13 cout<<"調用拷貝構造函數"<<endl; 14 Name=stu.Name; 15 Age=stu.Age; 16 } 17 Student& operator=(const Student& stu){ 18 cout<<"調用賦值函數"<<endl; 19 if(this!=&stu){ 20 Name=stu.Name; 21 Age=stu.Age; 22 } 23 return *this; 24 } 25 Student* operator&(){ 26 cout<<"調用取地址函數"<<endl; 27 return this; 28 } 29 ~Student(){ 30 cout<<"調用析構函數"<<endl; 31 } 32 private: 33 string Name; 34 int Age; 35 }; 36 int main(){ 37 const Student stu("Tomwenxing",23); 38 cout<<"對象stu的地址為:"<<&stu<<endl;//成功:運行對對象stu進行取地址操作 39 return 0; 40 }
通過上面的例子我們發現,在對常對象stu進行取地址操作時,對象並沒有調用類中的取地址函數,這是因為類中還有一個默認的函數,其功能是對常對象進行取地址操作。和取地址函數相同,對常對象的取地址函數也是通過對取地址運算符&重載來實現的,同樣如果用戶在編寫類時沒有顯式地定義類的對常對象的取地址函數,那麽C++編譯器將會在類中生成一個默認的對常對象的取地址函數:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){ 7 cout<<"調用無參數的構造函數"<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){ 10 cout<<"調用有參數的構造函數"<<endl; 11 } 12 Student(const Student& stu){ 13 cout<<"調用拷貝構造函數"<<endl; 14 Name=stu.Name; 15 Age=stu.Age; 16 } 17 Student& operator=(const Student& stu){ 18 cout<<"調用賦值函數"<<endl; 19 if(this!=&stu){ 20 Name=stu.Name; 21 Age=stu.Age; 22 } 23 return *this; 24 } 25 Student* operator&(){ 26 cout<<"調用取地址函數"<<endl; 27 return this; 28 } 29 const Student* operator&() const{ 30 cout<<"調用對常對象的取地址函數"<<endl; 31 return this; 32 } 33 ~Student(){ 34 cout<<"調用析構函數"<<endl; 35 } 36 private: 37 string Name; 38 int Age; 39 }; 40 int main(){ 41 const Student stu("Tomwenxing",23); 42 cout<<"對象stu的地址為:"<<&stu<<endl;//成功:運行對常對象stu進行取地址操作 43 return 0; 44 }
特別註意:兩個const的作用
? 第一個const要求函數返回的指針是常量,如果返回的是非常量則報錯
? 第二個const修飾this指針,使該對象的this指針是一個指針常量,從而能夠被該函數成功返回。
C++:類中兩個易被忽略的默認函數