自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

適合具備 C 語言基礎(chǔ)的 C++ 教程之二

開發(fā) 后端
在上一則教程中,通過與 C 語言相比較引出了 C++ 的相關(guān)特性,其中就包括函數(shù)重載,引用,this 指針,以及在脫離 IDE 編寫 C++ 程序時(shí),所要用到的 Makefile的相關(guān)語法。

 [[381641]]

前言

在上一則教程中,通過與 C 語言相比較引出了 C++ 的相關(guān)特性,其中就包括函數(shù)重載,引用,this 指針,以及在脫離 IDE 編寫 C++ 程序時(shí),所要用到的 Makefile的相關(guān)語法。本節(jié)所要敘述的是 C++的另外兩個(gè)重要的特性,也就是構(gòu)造函數(shù)和析構(gòu)函數(shù)的相關(guān)內(nèi)容,這兩部分內(nèi)容也是有別于 c語言而存在的,也是 c++的一個(gè)重要特性。

構(gòu)造函數(shù)

類的構(gòu)造函數(shù)是類的一種特殊的成員函數(shù),它會(huì)在每次創(chuàng)建新的對(duì)象的時(shí)候執(zhí)行,構(gòu)造函數(shù)的名稱和類的名稱是完全相同的,并不會(huì)返回任何的類型,也不會(huì)返回 void。構(gòu)造函數(shù)可以用于為某些成員變量設(shè)置初始值。

比方說,我們現(xiàn)在有如下所示的一段代碼:

  1. #include <iostream> 
  2. using namespace std; 
  3.  
  4. class Person{ 
  5. private: 
  6.     char *name
  7.     int age; 
  8.     char *work
  9.  
  10. public
  11.     Person() {cout << "Person()" << endl;} 
  12. }; 
  13.  
  14. int main(int argc, char **argv) 
  15.     Person per; 
  16.  
  17.     return 0; 

在主函數(shù)中,定義 Person per 的同時(shí),就會(huì)自動(dòng)地調(diào)用 Person() 函數(shù),那么不難猜出,執(zhí)行 test 文件的時(shí)候,輸出結(jié)果如下:

image-20210113124209248

上述的構(gòu)造函數(shù)并沒有參數(shù),實(shí)際上在構(gòu)造函數(shù)是可以具有參數(shù)的,具體的看如下所示的代碼:

  1. #include <iostream> 
  2. using namespace std; 
  3.  
  4. class Person 
  5. private: 
  6.     char *name
  7.     int age; 
  8. public
  9.     Person(char *nameint age) 
  10.     { 
  11.         cout << "Person(char *,int)" << endl; 
  12.         this->name = name
  13.         this->age = age; 
  14.     } 
  15.  
  16.     Person(){cout << "Person()" << endl;} 
  17. }; 
  18.  
  19. int main(int argc, char **argv) 
  20.     Person per; 
  21.     Person per2("zhangsan",18); 
  22.  
  23.     return 0; 

上述代碼中,定義第一個(gè) Person 實(shí)例的時(shí)候,就會(huì)自動(dòng)地調(diào)用無形參地構(gòu)造函數(shù),當(dāng)實(shí)例化第二個(gè) Person 類的時(shí)候,就會(huì)自動(dòng)地調(diào)用有形參地構(gòu)造函數(shù)。

這個(gè)時(shí)候,運(yùn)行函數(shù)的輸出結(jié)果如下所示:

image-20210113125016221

可以看到調(diào)用構(gòu)造函數(shù)的順序是和實(shí)例化對(duì)象的順序是一致的。

構(gòu)造函數(shù)除了可以有形參,也可以有默認(rèn)的形參,比如說下面這段代碼:

  1. #include <iostream> 
  2. using namespace std; 
  3.  
  4. class Person 
  5. private: 
  6.     char *name
  7.     int age; 
  8. public
  9.     Person(char *nameint age, char *work = "none"
  10.     { 
  11.         cout << "Person(char *,int)" << endl; 
  12.         this->name = name
  13.         this->age = age; 
  14.         this->work = work
  15.     } 
  16.  
  17.     Person(){cout << "Person()" << endl;} 
  18.  
  19.     void printInfo(void) 
  20.     { 
  21.         cout << "name =" << name << ",age = "<< age << ",work ="<< work << endl; 
  22.     } 
  23. }; 
  24.  
  25. int main(int argc, char **argv) 
  26.     Person per; 
  27.     Person per2("zhangsan",18); 
  28.     Person per3(); 
  29.  
  30.     per2.printInfo(); 
  31.  
  32.     return 0; 

上述代碼中,第一條代碼和第二條代碼創(chuàng)建了兩個(gè) Person 實(shí)例,在創(chuàng)建時(shí)依次調(diào)用構(gòu)造函數(shù),這里需要注意的是,第三條語句,這條語句看起來像是實(shí)例化了一個(gè) per3 對(duì)象,但是 per3 括號(hào)里并沒有實(shí)參,這其實(shí)是定義了一個(gè)函數(shù),函數(shù)的形參為void,返回值為 Person ,并非是一個(gè)對(duì)象。這里還需要注意的一點(diǎn)是 per2 對(duì)象,它在調(diào)用構(gòu)造函數(shù)時(shí),形參有一個(gè)默認(rèn)值,所以最終,程序輸出的結(jié)果如下所示:

image-20210113131653000

在實(shí)例化對(duì)象的時(shí)候,我們也可以通過定義指針的形式實(shí)現(xiàn),下面代碼是上述代碼的一個(gè)改進(jìn),并且以指針的形式實(shí)例化了對(duì)象,代碼如下所示:

  1. #include <iostream> 
  2. #include <string.h> 
  3.  
  4. using namespace std; 
  5.  
  6. class Person 
  7. private: 
  8.     char *name
  9.     int age; 
  10.     char *work
  11.  
  12. public
  13.     Person(){cout << "person()" << endl;} 
  14.     Person(char *name,int age, char *work
  15.     { 
  16.         cout << "Person(char *,int, char *)" << endl; 
  17.         this->name = new char[strlen(name) + 1]; 
  18.         strcpy(this->name,name); 
  19.         this->age = age; 
  20.         this->work = new char[strlen(work) + 1]; 
  21.         strcpy(this->work,work); 
  22.     } 
  23.  
  24.     void printInfo(void) 
  25.     { 
  26.         cout << "name is:" << name << ",age is:" << age << ",work is:" << work << endl; 
  27.     } 
  28. }; 
  29.  
  30. int main(int argc,char *argv) 
  31.     Person per("zhangsan",18,"teacher"); 
  32.     Person per2; 
  33.  
  34.     Person *per4 = new Person; 
  35.     Person *per5 = new Person(); /* 這兩種方式定義的效果是一樣的 */ 
  36.  
  37.     Person *per6 = new Person[2]; 
  38.  
  39.     Person *per7 = new Person("lisi", 18,"doctor"); 
  40.     per.printInfo(); 
  41.     per7.printInfo(); 
  42.  
  43.     delete per4; 
  44.     delete per5; 
  45.     delete []per6; 
  46.     delete per7; 

上述代碼中,使用了new 來分配給對(duì)象空間,再分配完之后,系統(tǒng)會(huì)自動(dòng)的進(jìn)行釋放,或者說是使用手動(dòng)的方式進(jìn)行釋放內(nèi)存,在手動(dòng)釋放內(nèi)存的時(shí)候,我們采用 delete 的方式來進(jìn)行釋放,當(dāng)創(chuàng)建了兩個(gè)指針數(shù)組的時(shí)候,在手動(dòng)釋放的時(shí)候,要在指針變量前面加上 [],在實(shí)例化指針對(duì)象的時(shí)候,也可以帶上參數(shù)或者說是不帶參數(shù)。下面是上述代碼的運(yùn)行結(jié)果:

image-20210114125841211

析構(gòu)函數(shù)

析構(gòu)函數(shù)的引出

上述我們知道,在函數(shù)運(yùn)行完之后,用 new 分配到的空間才會(huì)被釋放掉,那么如果是在函數(shù)調(diào)用里用 new 獲取到的空間會(huì)隨著函數(shù)調(diào)用的結(jié)束而釋放么,我們現(xiàn)在來做這樣一個(gè)實(shí)驗(yàn),把上述中的代碼中的主函數(shù)寫成 test()函數(shù),然后在 main() 函數(shù)里調(diào)用。

代碼如下所示:

  1. #include <iostream> 
  2. #include <string.h> 
  3. #include <unistd.h> 
  4.  
  5. using namespace std; 
  6.  
  7. class Person 
  8. private: 
  9.     char *name
  10.     int age; 
  11.     char *work
  12.  
  13. public
  14.     Person(){cout << "person()" << endl;} 
  15.     Person(char *name,int age, char *work
  16.     { 
  17.         cout << "Person(char *,int, char *)" << endl; 
  18.         this->name = new char[strlen(name) + 1]; 
  19.         strcpy(this->name,name); 
  20.         this->age = age; 
  21.         this->work = new char[strlen(work) + 1]; 
  22.         strcpy(this->work,work); 
  23.     } 
  24.  
  25.     void printInfo(void) 
  26.     { 
  27.         //cout << "name is:" << name << ",age is:" << age << ",work is:" << work << endl; 
  28.     } 
  29. }; 
  30.  
  31. void test(void) 
  32.     Person per("zhangsan",18,"teacher"); 
  33.     Person per2; 
  34.  
  35.     Person *per4 = new Person; 
  36.     Person *per5 = new Person(); /* 這兩種方式定義的效果是一樣的 */ 
  37.  
  38.     Person *per6 = new Person[2]; 
  39.  
  40.     Person *per7 = new Person("lisi", 18,"doctor"); 
  41.     per.printInfo(); 
  42.     per7->printInfo(); 
  43.  
  44.     delete per4; 
  45.     delete per5; 
  46.     delete []per6; 
  47.     delete per7; 
  48.  
  49. int main(int argc, char **argv) 
  50.     for (int i = 0; i < 1000000; i++) 
  51.         test(); 
  52.     cout << "run test end" << endl; 
  53.     sleep(10); 
  54.     return 0; 

這是運(yùn)行前的空閑內(nèi)存的大小:

image-20210114133025365

緊接著是函數(shù)運(yùn)行完 100 0000 次的 test 函數(shù)之后的空閑內(nèi)存大?。?/p>

image-20210114133140216

然后,是主函數(shù)運(yùn)行完之后,推出主函數(shù)之后,空閑的內(nèi)存剩余量:

image-20210114133241325

總結(jié)一下就是,在子函數(shù)里用 new 分配給局部變量的空間,具體來說在上述代碼中的體現(xiàn)就是用 new給 this->name分配的空間。也就是在主函數(shù)沒有運(yùn)行完是不會(huì)被釋放掉的,也就是說只有在主函數(shù)運(yùn)行完之后,子函數(shù)里用 new 分配的空間才會(huì)被釋放掉,因此,如果想要在子函數(shù)調(diào)用完之后就釋放掉用 new 分配的空間,就需要編寫代碼來實(shí)現(xiàn)。而這個(gè)操作, C++ 提供了析構(gòu)函數(shù)來完成,下面是使用析構(gòu)函數(shù)來進(jìn)行釋放內(nèi)存的代碼:

  1. #include <iostream> 
  2. #include <string.h> 
  3. #include <unistd.h> 
  4.  
  5. using namespace std; 
  6.  
  7. class Person 
  8. private: 
  9.     char *name
  10.     int age; 
  11.     char *work
  12.  
  13. public
  14.     Person(){cout << "person()" << endl;} 
  15.     Person(char *name,int age, char *work
  16.     { 
  17.         cout << "Person(char *,int, char *)" << endl; 
  18.         this->name = new char[strlen(name) + 1]; 
  19.         strcpy(this->name,name); 
  20.         this->age = age; 
  21.         this->work = new char[strlen(work) + 1]; 
  22.         strcpy(this->work,work); 
  23.     } 
  24.  
  25.     ~Person() 
  26.     { 
  27.         if (this->name
  28.             delete this->name
  29.         if (this->work
  30.             delete this->work
  31.     } 
  32.  
  33.     void printInfo(void) 
  34.     { 
  35.         //cout << "name is:" << name << ",age is:" << age << ",work is:" << work << endl; 
  36.     } 
  37. }; 
  38.  
  39. void test(void) 
  40.     Person per("zhangsan",18,"teacher"); 
  41.     Person per2; 
  42.  
  43.     Person *per4 = new Person; 
  44.     Person *per5 = new Person(); /* 這兩種方式定義的效果是一樣的 */ 
  45.  
  46.     Person *per6 = new Person[2]; 
  47.  
  48.     Person *per7 = new Person("lisi", 18,"doctor"); 
  49.     per.printInfo(); 
  50.     per7->printInfo(); 
  51.  
  52.     delete per4; 
  53.     delete per5; 
  54.     delete []per6; 
  55.     delete per7; 
  56.  
  57. int main(int argc, char **argv) 
  58.     for (int i = 0; i < 1000000; i++) 
  59.         test(); 
  60.     cout << "run test end" << endl; 
  61.     sleep(10); 
  62.     return 0; 

下述就是代碼運(yùn)行之前,和主函數(shù)在休眠的時(shí)候的剩余內(nèi)存的容量,可以看出,剩余內(nèi)存的容量是一樣的,換句話說,也就是在 test()函數(shù)運(yùn)行完成之后,用 new 分配的空間就已經(jīng)被釋放掉了,就算執(zhí)行了 1000000 次也沒有造成內(nèi)存泄漏。這也說明了我們的析構(gòu)函數(shù)是有作用的。

image-20210115130212394

析構(gòu)函數(shù)在什么地方被調(diào)用

上述析構(gòu)函數(shù)的存在避免了內(nèi)存泄漏,那么析構(gòu)函數(shù)是在什么時(shí)候被調(diào)用的呢,用一句話描述就是:在實(shí)例化對(duì)象被銷毀的前一瞬間被調(diào)用的,另外還要注意的是構(gòu)造函數(shù)可以有很多個(gè),有參的,無參的構(gòu)造函數(shù),但是對(duì)于析構(gòu)函數(shù)來講,它只有一個(gè),并且它是無參的。具體的來看如下所示的代碼,在剛才那段代碼的基礎(chǔ)上,我們添加一些打印信息,從而推斷我們析構(gòu)函數(shù)調(diào)用的位置:

  1. #include <iostream> 
  2. #include <string.h> 
  3. #include <unistd.h> 
  4.  
  5. using namespace std; 
  6.  
  7. class Person 
  8. private: 
  9.     char *name
  10.     int age; 
  11.     char *work
  12.  
  13. public
  14.     Person() 
  15.     { 
  16.         name = NULL
  17.         work = NULL
  18.     } 
  19.     Person(char *name,int age, char *work
  20.     { 
  21.         this->name = new char[strlen(name) + 1]; 
  22.         strcpy(this->name,name); 
  23.         this->age = age; 
  24.         this->work = new char[strlen(work) + 1]; 
  25.         strcpy(this->work,work); 
  26.     } 
  27.  
  28.     ~Person() 
  29.     { 
  30.         cout << "~Person()" << endl; 
  31.         if (this->name
  32.         { 
  33.             delete this->name
  34.             cout << "The name is:" << name << endl;    
  35.         } 
  36.         if (this->work
  37.         { 
  38.             delete this->work
  39.             cout << "The work is:" << work << endl; 
  40.         } 
  41.     } 
  42.  
  43.     void printInfo(void) 
  44.     { 
  45.         //cout << "name is:" << name << ",age is:" << age << ",work is:" << work << endl; 
  46.     } 
  47. }; 
  48.  
  49. void test(void) 
  50.     Person per("zhangsan",18,"teacher"); 
  51.  
  52.     Person *per7 = new Person("lisi", 18,"doctor"); 
  53.     delete per7; 
  54.  
  55. int main(int argc, char **argv) 
  56.     test(); 
  57.     return 0; 

我們來看輸出的結(jié)果:

image-20210115132418481

通過上面的輸出結(jié)果可以知道,先輸出的是lisi,后輸出的是 zhangsan,而在實(shí)例化對(duì)象的時(shí)候,是先創(chuàng)建的 per 對(duì)象,并初始化為 zhangsan,后創(chuàng)建的 per7 對(duì)象,并初始化為 lisi,再調(diào)用析構(gòu)函數(shù)的時(shí)候順序卻是顛倒過來的。因此,總結(jié)一下就是:

per 這個(gè)實(shí)例化對(duì)象是在 test()函數(shù)執(zhí)行完之后,再調(diào)用的析構(gòu)函數(shù),而對(duì)于 per7對(duì)象來說,是在執(zhí)行 delete per7這條語句之后調(diào)用的析構(gòu)函數(shù),所以也就有了上述的輸出結(jié)果。

另外,引出一點(diǎn),如果我們?cè)谏鲜龅拇a中把delete per7這條語句給注釋掉,那么會(huì)怎么樣呢,下圖是去掉該語句之后的結(jié)果:

image-20210115133215468

我們看到,上述就只執(zhí)行了 zhangsan的析構(gòu)函數(shù),并沒有執(zhí)行l(wèi)isi的析構(gòu)函數(shù),這也告訴我們,在使用 new 創(chuàng)建的實(shí)例化對(duì)象,必須使用 delete 將其釋放掉,如果沒有使用 delete 來將其釋放,那么在系統(tǒng)退出之后,會(huì)自動(dòng)地釋放掉它地內(nèi)存,但是這個(gè)時(shí)候是不會(huì)調(diào)用它地析構(gòu)函數(shù)的。

最后,關(guān)于構(gòu)造函數(shù)和析構(gòu)函數(shù),如果類里沒有實(shí)現(xiàn)任何構(gòu)造函數(shù)和析構(gòu)函數(shù),那么其系統(tǒng)本身會(huì)調(diào)用一個(gè)默認(rèn)的構(gòu)造函數(shù)和析構(gòu)函數(shù)。那么,除了默認(rèn)的構(gòu)造函數(shù)和默認(rèn)的析構(gòu)函數(shù),還存在一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),接下來,來敘述這個(gè)拷貝構(gòu)造函數(shù)。

拷貝構(gòu)造函數(shù)

默認(rèn)拷貝構(gòu)造函數(shù)

我們直接來看這樣一段代碼:

  1. #include <iostream> 
  2. #include <string.h> 
  3. #include <unistd.h> 
  4.  
  5. using namespace std; 
  6.  
  7. class Person { 
  8. private: 
  9.     char *name
  10.     int age; 
  11.     char *work
  12.  
  13. public
  14.  
  15.     Person() {//cout <<"Pserson()"<<endl; 
  16.         name = NULL
  17.         work = NULL
  18.     } 
  19.     Person(char *name)  
  20.     { 
  21.         //cout <<"Pserson(char *)"<<endl; 
  22.         this->name = new char[strlen(name) + 1]; 
  23.         strcpy(this->namename); 
  24.         this->work = NULL
  25.     } 
  26.  
  27.     Person(char *nameint age, char *work = "none")  
  28.     { 
  29.         //cout <<"Pserson(char*, int)"<<endl; 
  30.         this->age = age; 
  31.  
  32.         this->name = new char[strlen(name) + 1]; 
  33.         strcpy(this->namename); 
  34.  
  35.         this->work = new char[strlen(work) + 1]; 
  36.         strcpy(this->workwork); 
  37.     } 
  38.  
  39.     ~Person() 
  40.     { 
  41.         cout << "~Person()"<<endl; 
  42.         if (this->name) { 
  43.             cout << "name = "<<name<<endl; 
  44.             delete this->name
  45.         } 
  46.         if (this->work) { 
  47.             cout << "work = "<<work<<endl; 
  48.             delete this->work
  49.         } 
  50.     } 
  51.  
  52.     void printInfo(void) 
  53.     { 
  54.         //printf("name = %s, age = %d, work = %s\n"name, age, work);  
  55.         cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl; 
  56.     } 
  57. }; 
  58.  
  59. int main(int argc, char **argv) 
  60.     Person per("zhangsan", 18); 
  61.     Person per2(per); 
  62.  
  63.     per2.printInfo(); 
  64.  
  65.     return 0; 

在主函數(shù)的第二行代碼中,我們可以看到我們創(chuàng)建了一個(gè)實(shí)例,并且傳入的參數(shù)是 per,但是我們看類里面的代碼實(shí)現(xiàn),并沒有發(fā)現(xiàn)有一個(gè)構(gòu)造函數(shù)的形參為 Person ,那這個(gè)時(shí)候,會(huì)發(fā)生什么函數(shù)調(diào)用呢,實(shí)際上是會(huì)調(diào)用一個(gè)系統(tǒng)的默認(rèn)構(gòu)造函數(shù),這個(gè)默認(rèn)的構(gòu)造函數(shù)會(huì)進(jìn)行值拷貝,會(huì)將 per中的內(nèi)容拷貝到 per2中去,下圖是這個(gè)過程的一個(gè)示意圖:

image-20210117015212259.png

通過上圖可以看到,在執(zhí)行默認(rèn)的拷貝構(gòu)造函數(shù)的時(shí)候,執(zhí)行的是值拷貝,那么相應(yīng)的,per 的 name 也就指向了 address1,per2 的 name 同樣也指向了 adress,從而完成了值拷貝的過程,下面是代碼運(yùn)行的結(jié)果:

image-20210117015527675

可以看到,在輸出 per2 的內(nèi)容的時(shí)候,輸出的是 per 的初始化內(nèi)容,在主函數(shù)運(yùn)行完之后,就要執(zhí)行析構(gòu)函數(shù)來釋放使用 new 分配的空間,首先是釋放 per 的內(nèi)容,然后緊接著是釋放 per2的內(nèi)容,但是在剛剛的敘述中,使用默認(rèn)構(gòu)造函數(shù)進(jìn)行拷貝的時(shí)候,使用的是值拷貝,從而造成的效果是 per2 的 name 和 work 指向的地址是 per 中的同一塊地址,這樣,在執(zhí)行析構(gòu)函數(shù)的時(shí)候,同一塊內(nèi)存空間就會(huì)被釋放兩次,從而導(dǎo)致錯(cuò)誤。因此,使用默認(rèn)的拷貝構(gòu)造函數(shù)存在一定的問題,也就需要我們自己來定義拷貝構(gòu)造函數(shù),下面介紹自定義的拷貝構(gòu)造函數(shù)。

自定義拷貝構(gòu)造函數(shù)

我們根據(jù)在上述代碼的基礎(chǔ)上,修改得到我們自定義的拷貝構(gòu)造函數(shù)如下:

  1. #include <iostream> 
  2. #include <string.h> 
  3. #include <unistd.h> 
  4.  
  5. using namespace std; 
  6.  
  7. class Person { 
  8. private: 
  9.     char *name
  10.     int age; 
  11.     char *work
  12.  
  13. public
  14.  
  15.     Person() {//cout <<"Pserson()"<<endl; 
  16.         name = NULL
  17.         work = NULL
  18.     } 
  19.     Person(char *name)  
  20.     { 
  21.         //cout <<"Pserson(char *)"<<endl; 
  22.         this->name = new char[strlen(name) + 1]; 
  23.         strcpy(this->namename); 
  24.         this->work = NULL
  25.     } 
  26.  
  27.     Person(char *nameint age, char *work = "none")  
  28.     { 
  29.         cout <<"Pserson(char*, int)"<<endl; 
  30.         this->age = age; 
  31.  
  32.         this->name = new char[strlen(name) + 1]; 
  33.         strcpy(this->namename); 
  34.  
  35.         this->work = new char[strlen(work) + 1]; 
  36.         strcpy(this->workwork); 
  37.     } 
  38.  
  39.     Person(Person &per)  
  40.     { 
  41.         cout <<"Pserson(Person &per)"<<endl; 
  42.         this->age = per.age; 
  43.  
  44.         this->name = new char[strlen(per.name) + 1]; 
  45.         strcpy(this->name, per.name); 
  46.  
  47.         this->work = new char[strlen(per.work) + 1]; 
  48.         strcpy(this->work, per.work); 
  49.     } 
  50.  
  51.     ~Person() 
  52.     { 
  53.         cout << "~Person()"<<endl; 
  54.         if (this->name) { 
  55.             cout << "name = "<<name<<endl; 
  56.             delete this->name
  57.         } 
  58.         if (this->work) { 
  59.             cout << "work = "<<work<<endl; 
  60.             delete this->work
  61.         } 
  62.     } 
  63.  
  64.     void printInfo(void) 
  65.     { 
  66.         //printf("name = %s, age = %d, work = %s\n"name, age, work);  
  67.         cout<<"name = "<<name<<", age = "<<age<<", work = "<<work<<endl; 
  68.     } 
  69. }; 
  70.  
  71. int main(int argc, char **argv) 
  72.     Person per("zhangsan", 18); 
  73.     Person per2(per); 
  74.  
  75.     per2.printInfo(); 
  76.  
  77.     return 0; 

上述中,我們編寫了一個(gè)拷貝構(gòu)造函數(shù),函數(shù)的形參是 Person 類的引用,然后我們?cè)谥骱瘮?shù)中傳入 per 實(shí)參,程序執(zhí)行的結(jié)果如下圖所示:

image-20210117234707175

通過圖片代碼的運(yùn)行結(jié)果我們也可以知道,在執(zhí)行主函數(shù)的第二行代碼的時(shí)候,調(diào)用了默認(rèn)的拷貝構(gòu)造函數(shù)。

對(duì)象的構(gòu)造順序

在上述代碼的基礎(chǔ)上,比如說我們存在如下幾個(gè)實(shí)例化對(duì)象。

  1. Person per_g("per_g", 10); 
  2.  
  3. void func(void) 
  4.     Person per_func("per_func",11); 
  5.     static Person per_func_s("per_func_s",11); 
  6.  
  7. int main(int argc,char **argv) 
  8.     Person per_main("per_main",11); 
  9.     static Person person_main_s("person_main_s",11); 
  10.  
  11.     for (int i = 0; i < 2; i++) 
  12.     { 
  13.         func(); 
  14.         Person per_for("per_for",i); 
  15.     } 
  16.  
  17.     return 0; 

緊接著,我們來看上述代碼的執(zhí)行結(jié)果,結(jié)果如下圖所示:

image-20210118000045599

通過上述的結(jié)果,我們可以得出:

實(shí)例化類的構(gòu)造順序是按照定義的順序進(jìn)行構(gòu)造的,全局的實(shí)例化對(duì)象會(huì)在主函數(shù)執(zhí)行前被構(gòu)造,然后緊接著構(gòu)造的是在主函數(shù)定義的實(shí)例化對(duì)象 per_main 和 per_main_s,構(gòu)造的順序不會(huì)因?yàn)槠鋵?shí)例化對(duì)象是 static 而發(fā)生改變,緊接著就是函數(shù) func里面的 per_func和 per_func_s。在退出 func的時(shí)候,會(huì)釋放掉 func中的局部變量,這個(gè)時(shí)候會(huì)調(diào)用 per_func的析構(gòu)函數(shù),但是這時(shí)是不會(huì)釋放掉 func中的 per_func_s,因?yàn)樗?static 的,緊接著會(huì)構(gòu)造 per_for對(duì)象,當(dāng)一個(gè) for循析構(gòu)函數(shù)。環(huán)執(zhí)行完畢之后,就會(huì)將剛剛那個(gè)構(gòu)造的 per_for對(duì)象釋放掉,也就是會(huì)調(diào)用析構(gòu)函數(shù)。緊接著,我們繼續(xù)調(diào)用 func函數(shù),在 func函數(shù)里面,會(huì)執(zhí)行 per_fun的構(gòu)造函數(shù),但是不會(huì)執(zhí)行 per_fun_s的構(gòu)造函數(shù),因?yàn)橐呀?jīng)構(gòu)造過了,在最后,主函數(shù)運(yùn)行完畢之后,以此釋放實(shí)例化的空間,首先會(huì)釋放掉 per_main,然后釋放 per_main_s,緊接著釋放全局變量的空間per_g。

在類里初始化類對(duì)象

在剛剛說到的類里面,我們繼續(xù)添加新的代碼,同樣的,我們有如下所示的這樣一個(gè)類:

  1. class 
  2. private: 
  3.     Person father; 
  4.     Person mother; 
  5.     int student_id; 
  6. public
  7.     Student(int id, char *father, char *mother, int father_age = 49, int mother_age = 39) : mother(mother,mother_age),father(father,father_age) 
  8.     { 
  9.         cout << "Student(int id, char *father, char *mother, int father_age, int mother_age)" << endl; 
  10.     } 
  11. }; 
  12.  
  13. int main(int argc, char **argv) 
  14.     Student s(100,"Bill","Lisa"
  15.  
  16.     return 0; 

上述代碼運(yùn)行就會(huì)輸出如下所示的信息:

image-20210119131136755

這樣的操作,就會(huì)首先調(diào)用的是 father的構(gòu)造函數(shù),然后,緊接著再調(diào)用的是 mother的構(gòu)造函數(shù),然后,才是調(diào)用的 Student的構(gòu)造函數(shù),在主函數(shù)執(zhí)行完畢之后,執(zhí)行析構(gòu)函數(shù)的順序又和剛剛的相反。

小結(jié)

上述便是關(guān)于 C++比較核心的兩個(gè)概念,構(gòu)造函數(shù)以及析構(gòu)函數(shù)兩大特性,除了講述了兩大特性的基本概念之外,也敘述了為什么要適用析構(gòu)函數(shù),以及析構(gòu)函數(shù)調(diào)用的位置,同時(shí)也敘述了拷貝構(gòu)造函數(shù)的相關(guān)內(nèi)容。在本節(jié)的末尾也講述了構(gòu)造的順序以及析構(gòu)的順序,最后,給出了一種在類里面初始化類對(duì)象的一種方法。

本文轉(zhuǎn)載自微信公眾號(hào)「 wenzi嵌入式軟件」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系 wenzi嵌入式軟件公眾號(hào)。

 

責(zé)任編輯:武曉燕 來源: wenzi嵌入式軟件
相關(guān)推薦

2021-02-21 12:09:32

C 語言基礎(chǔ)語法

2021-02-20 06:13:18

C 語言C++

2021-02-16 10:57:34

C++ C 語言windows

2021-02-08 20:25:12

C 語言C++Linux

2021-07-16 07:21:45

C++可調(diào)用對(duì)象std::functi

2011-07-14 16:56:21

2010-01-15 17:38:37

C++語言

2010-01-19 14:45:35

C++語言

2020-08-21 13:20:36

C++If ElseLinux

2021-04-25 08:11:57

C語言常量與變量標(biāo)識(shí)符命名規(guī)范

2011-07-14 17:45:06

CC++

2011-07-14 17:17:21

C++指針

2011-07-15 00:47:13

C++多態(tài)

2021-02-06 07:49:48

C語言編程開發(fā)技術(shù)

2011-01-05 11:12:34

C++

2022-01-14 09:10:56

C++文件Linux

2011-07-13 18:24:18

C++

2020-07-30 12:40:35

CC++編程語言

2011-05-18 18:05:47

C#C++

2022-07-01 11:56:54

C語言C++編程語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)