C++:建構函式2——拷貝建構函式
阿新 • • 發佈:2018-12-12
前言:拷貝建構函式是C++中的重點之一,在這裡對其知識進行一個簡單的總結。
一、什麼是拷貝建構函式
在C++中,對於內建型別的變數來說,在其建立的過程中用同類型的另一個變數來初始化它是完全可以的,如:
1 int value=100; 2 int new_value=value;//在變數new_value建立的同時用同類型的變數value來初始化它
那麼對於自定義的資料型別來說,是否可以在該類的一個物件建立時用該類的另一個物件對其進行初始化呢?看下例:
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student()=default;//預設建構函式 7 Student(string name,int age):Name(name),Age(age){} //建構函式 8 ~Student(){}//解構函式 9 void message();//列印物件的資訊 10 private: 11 string Name; 12 int Age; 13 }; 14 15 void Student::message(){ 16 cout<<"My name is "<<Name<<endl; 17 cout<<"I am "<<Age<<" years old"<<endl; 18 } 19 int main(){ 20 Student stu1("Tomwenxing",23); 21 Student stu2(stu1);22 stu2.message(); 23 return 0; 24 }
由上面的例子可以看出可以用一個類的物件去對該類的另一個正在建立的新物件進行初始化。而完成這個工作的就是類中的拷貝建構函式。所謂拷貝建構函式是一種特殊的建構函式,它由編譯器呼叫來完成一些基於同一類的其他物件的構建及初始化。如果程式設計者在編寫自定義的類時沒有自定義拷貝建構函式,那麼編譯器會在類中定義一個預設的拷貝建構函式。
語法:類名(const 類名 &物件名) { /*拷貝建構函式體*/}
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student()=default;//預設建構函式 7 Student(string name,int age):Name(name),Age(age){} //建構函式 8 Student(const Student& stu){ //拷貝建構函式9 Name=stu.Name; 10 Age=stu.Age; 11 cout<<"呼叫了拷貝建構函式!"<<endl; 12 } 13 ~Student(){}//解構函式 14 void message();//列印物件的資訊 15 private: 16 string Name; 17 int Age; 18 }; 19 20 void Student::message(){ 21 cout<<"My name is "<<Name<<endl; 22 cout<<"I am "<<Age<<" years old"<<endl; 23 } 24 int main(){ 25 Student stu1("Tomwenxing",23); 26 Student stu2(stu1); 27 stu2.message(); 28 return 0; 29 }
特別注意:
拷貝建構函式的函式名必須和類名相同,且其唯一的引數(物件的引用)是不可變的(const型別)
二、拷貝建構函式的呼叫
在C++中,有三種情況會使物件在建立時呼叫拷貝建構函式
case 1:物件以值傳遞的方式傳入函式引數
當物件直接作為引數以值傳遞的方式傳遞給函式時,函式將呼叫類中的拷貝建構函式並將實參物件傳遞給該拷貝建構函式從而在記憶體中建立形參物件,該形參物件將在函式執行完畢後呼叫類的解構函式將其析構
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){//預設建構函式 7 cout<<"呼叫了預設建構函式 "<<this<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){//建構函式1 10 cout<<"呼叫了建構函式1 "<<this<<endl; 11 } 12 Student(const Student& stu){ 13 Name=stu.Name; 14 Age=stu.Age; 15 cout<<"呼叫了拷貝建構函式!"<<this<<endl; 16 } 17 ~Student(){//解構函式 18 cout<<"呼叫了解構函式 "<<this<<endl; 19 } 20 void message();//列印物件的資訊 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message(){ 27 cout<<"My name is "<<Name<<endl; 28 cout<<"I am "<<Age<<" years old"<<endl; 29 } 30 31 void func1(Student s){ 32 cout<<"呼叫了函式func1"<<endl; 33 cout<<"形參變數的地址為"<<&s<<endl; 34 } 35 int main(){ 36 Student stu("Tomwenxing",23); 37 cout<<"實參變數的地址為"<<&stu<<endl; 38 cout<<"準備呼叫函式func1"<<endl; 39 func1(stu); 40 cout<<"函式func1調研完畢"<<endl; 41 return 0; 42 }
case 2:物件以值傳遞的方式從函式返回
當物件以值傳遞的方式從函式返回時,函式會呼叫類中的拷貝建構函式並將要返回的物件傳遞給該拷貝建構函式從而在記憶體中建立一個臨時物件,該臨時物件會在返回後(不管有沒有物件接收(拷貝)該臨時物件)立馬呼叫類中的解構函式進行析構。
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student { 5 public: 6 Student() {//預設建構函式 7 cout << "呼叫了預設建構函式 " << this << endl; 8 } 9 Student(string name, int age) :Name(name), Age(age) {//建構函式1 10 cout << "呼叫了建構函式1 " << this << endl; 11 } 12 Student(const Student& stu) { 13 Name = stu.Name; 14 Age = stu.Age; 15 cout << "呼叫了拷貝建構函式!" << this << endl; 16 } 17 ~Student() {//解構函式 18 cout << "呼叫了解構函式 " << this << endl; 19 } 20 void message();//列印物件的資訊 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message() { 27 cout << "My name is " << Name << endl; 28 cout << "I am " << Age << " years old" << endl; 29 } 30 31 Student func1() { 32 cout << "呼叫了函式func1" << endl; 33 Student s("Tomwenxing", 23); 34 cout << "函式中的區域性物件s在記憶體中的地址:" << &s << endl; 35 return s; 36 } 37 int main() { 38 cout << "準備呼叫函式func1" << endl; 39 func1(); 40 cout << "函式func1調研完畢" << endl; 41 return 0; 42 }
case 3:物件在建立過程中被相同型別的其他物件初始化
當物件在建立過程中被同類型的其他物件進行初始化時,該物件會呼叫類中的拷貝建構函式並將對其初始化的物件作為實參傳遞給該類的拷貝建構函式,從而最終將本物件成功建立
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 class Student{ 5 public: 6 Student(){//預設建構函式 7 cout<<"呼叫了預設建構函式 "<<this<<endl; 8 } 9 Student(string name,int age):Name(name),Age(age){//建構函式1 10 cout<<"呼叫了建構函式1 "<<this<<endl; 11 } 12 Student(const Student& stu){ 13 Name=stu.Name; 14 Age=stu.Age; 15 cout<<"呼叫了拷貝建構函式!"<<this<<endl; 16 } 17 ~Student(){//解構函式 18 cout<<"呼叫了解構函式 "<<this<<endl; 19 } 20 void message();//列印物件的資訊 21 private: 22 string Name; 23 int Age; 24 }; 25 26 void Student::message(){ 27 cout<<"My name is "<<Name<<endl; 28 cout<<"I am "<<Age<<" years old"<<endl; 29 } 30 31 int main(){ 32 Student stu1("Tomwenxing",23); 33 Student stu2(stu1);//初始化形式一 34 Student stu3=stu1;//初始化形式二 35 return 0; 36 }