C++類的構(gòu)造與析構(gòu)特點及作用詳解
一、類的構(gòu)造函數(shù)
什么是構(gòu)造函數(shù)
和類具有相同名稱,并且沒有返回值類型的函數(shù),就是類的構(gòu)造函數(shù)
概念模糊、直接舉例:
#include <stdio.h>
#include <windows.h>
struct Test
{
Test() // 和類具有相同的名、并且沒有返回值
{
}
};
int main()
{
return 0;
}構(gòu)造函數(shù)的特點
直接先來說特點吧,然后論證:
1、構(gòu)造函數(shù)在定義對象的時候被調(diào)用
2、構(gòu)造函數(shù)可以進(jìn)行函數(shù)重載,可以有很多個
3、創(chuàng)建對象時默認(rèn)調(diào)用的是無參構(gòu)造
證明1:
構(gòu)造函數(shù)在定義對象的時候被調(diào)用;
論證如下:
#include <stdio.h>
struct Test
{
Test()
{
printf("你調(diào)用了構(gòu)造函數(shù)\n"); // 此處下斷點、如果該函數(shù)被調(diào)用肯定會停下來。
}
};
int main()
{
Test te;
printf("接力\n");
return 0;
}我們在Test()構(gòu)造的輸出語句上加斷點、當(dāng)程序調(diào)用Test的printf肯定會停下來,這個時候我們轉(zhuǎn)到反匯編,單步步過、直到函數(shù)返回之后,就能知到剛剛是在哪里調(diào)用的構(gòu)造函數(shù)了
vs2010:F7編譯、F5調(diào)試、ALT+8反匯編:

F10一直運(yùn)行到返回:

這里編譯器做了優(yōu)化,可以直接看出來是在Test定義對象的時候調(diào)用了構(gòu)造。
證明2:
構(gòu)造函數(shù)可以進(jìn)行函數(shù)重載,可以有很多個;
論證如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了構(gòu)造函數(shù)\n"); // 此處下斷點、如果該函數(shù)被調(diào)用肯定會停下來。
}
Test(int a)
{
printf("重載%d\n",a);
}
Test(int a, int b)
{
printf("重載%d\n",a+b);
}
};
int main()
{
Test te;
Test te1(1);
Test te2(1,1); // 注意、調(diào)用有參的構(gòu)造函數(shù)時,需要傳遞參數(shù)
system("pause");
return 0;
}重載了兩個,注意:調(diào)用有參數(shù)的構(gòu)造時,需要傳遞參數(shù)。
運(yùn)行可以通過:

證明3:
創(chuàng)建對象時默認(rèn)調(diào)用的是無參構(gòu)造;
論證如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test(int a)
{
printf("重載%d\n",a);
}
Test(int a, int b)
{
printf("重載%d\n",a+b);
}
};
int main()
{
Test te; // 普通定義對象的方式、不帶參數(shù)
system("pause");
return 0;
}首先我們刪除無參構(gòu)造,看看能否編譯通過:

不可以
然后刪除有參構(gòu)造:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了構(gòu)造函數(shù)\n"); // 此處下斷點、如果該函數(shù)被調(diào)用肯定會停下來。
}
};
int main()
{
Test te;
system("pause");
return 0;
}
可以
全部都加上:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了構(gòu)造函數(shù)\n"); // 此處下斷點、如果該函數(shù)被調(diào)用肯定會停下來。
}
Test(int a)
{
printf("重載%d\n",a);
}
Test(int a, int b)
{
printf("重載%d\n",a+b);
}
};
int main()
{
Test te;
system("pause");
return 0;
}運(yùn)行結(jié)果:

這已經(jīng)證明了,Test te;平常這樣定義對象的時候,調(diào)用的是無參構(gòu)造。如果需要調(diào)用有參構(gòu)造,必須傳入?yún)?shù);
這個特點很簡單、有參函數(shù)肯定要傳參嘛,所以定義對象的時候肯定要傳入?yún)?shù)啊;
但是這里建議無論什么時候?qū)戭?,最好還是寫上無參構(gòu)造,哪怕什么都不做也盡量寫上,避免不必要的麻煩。
構(gòu)造函數(shù)的作用
一般用于初始化類的成員
如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
int x;
int y;
int z;
Test()
{
}
Test(int x,int y,int z) // 構(gòu)造函數(shù)初始化對象
{
this->x = x;
this->y = y;
this->z = z;
}
};
int main()
{
Test te;
Test te1(1,2,3); // 定義對象并調(diào)用有參構(gòu)造進(jìn)行初始化
printf("%d %d %d\n",te1.x,te1.y,te1.z); // 輸出看看是否初始化成功
system("pause");
return 0;
}運(yùn)行如下:

初始化成功。
二、類的析構(gòu)函數(shù)
什么是析構(gòu)函數(shù)
類的構(gòu)造函數(shù)名前加上'~'這個符號,就是類的析構(gòu)函數(shù)
概念模糊、代碼如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了一次類的構(gòu)造函數(shù)\n");
}
~Test()
{
printf("你調(diào)用了一次類的析構(gòu)函數(shù)\n");
}
};
int main()
{
Test te;
// system("pause"); // 這里就不要讓程序停下來了,不然析構(gòu)不了
return 0;
}~Test(){}就這個樣子
析構(gòu)函數(shù)的特點
依然直接先來說特點,然后論證:
1、析構(gòu)函數(shù)不能重載、不能有參數(shù)
2、析構(gòu)函數(shù)在變量聲明周期結(jié)束時被調(diào)用
3、析構(gòu)函數(shù)被調(diào)用分兩種情況:堆棧中定義的對象、全局區(qū)中定義的對象
證明1:
析構(gòu)函數(shù)不能重載、不能有參數(shù);

編譯不通過。
既然不能有參數(shù),那重載更不可能了

證明成功。
證明2:
析構(gòu)函數(shù)在變量聲明周期結(jié)束時被調(diào)用;
局部變量的生命周期是在一個大括號內(nèi),即一個所處塊結(jié)束。
所以:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了一次類的構(gòu)造函數(shù)\n");
}
~Test()
{
printf("你調(diào)用了一次類的析構(gòu)函數(shù)\n");
}
};
int main()
{
{
Test te;
printf("te生命周期即將結(jié)束。\n");
} // 析構(gòu)應(yīng)該在這里被調(diào)用
printf("te生命周期結(jié)束。\n");
system("pause");
return 0;
}運(yùn)行結(jié)果如下:

斷點

結(jié)果

證明成功。
證明3:
析構(gòu)函數(shù)被調(diào)用分兩種情況:堆棧中定義的對象、全局區(qū)中定義的對象;
已知堆棧中定義的對象(局部變量)在塊語句結(jié)束之后就會被調(diào)用,那么帶有return的main函數(shù)是在返回前調(diào)用析構(gòu),還是返回后呢?
代碼如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了一次類的構(gòu)造函數(shù)\n");
}
~Test()
{
printf("你調(diào)用了一次類的析構(gòu)函數(shù)\n"); // 斷點--匯編
}
};
int main()
{
Test te;
// system("pause"); // 不要使用pause,不然無法返回
return 0;
}斷點-調(diào)試-匯編:

可以看到是在函數(shù)返回前被調(diào)用的。
如果在全局區(qū)定義的對象呢?
這個問題很難說,像我一樣定義兩個斷點就行了,如下:
#include <stdio.h>
#include <Windows.h>
struct Test
{
Test()
{
printf("你調(diào)用了一次類的構(gòu)造函數(shù)\n");
}
~Test() // 斷點
{
printf("你調(diào)用了一次類的析構(gòu)函數(shù)\n");
}
};
Test te;
int main()
{
// system("pause"); // 不要使用pause,不然無法返回
return 0; // 斷點
}
運(yùn)行:

發(fā)現(xiàn)一運(yùn)行就斷在了return,當(dāng)我們發(fā)F10繼續(xù)運(yùn)行的時候,并沒有直接調(diào)用析構(gòu),而是到了括號那里:

繼續(xù)F10:

通過翻譯,可以得知這就是進(jìn)程結(jié)束時的一些收尾工作。
繼續(xù)F10:

現(xiàn)在大概可以總結(jié)了,類的對象定義為全局變量時,是在main函數(shù)結(jié)束之后進(jìn)程退出之前,調(diào)用的析構(gòu)函數(shù)。
小結(jié)
當(dāng)類的對象定義為局部變量時(堆棧),定義這個對象的塊作用域結(jié)束時就會調(diào)用該對象的析構(gòu)函數(shù),如果在main函數(shù)這個塊作用域中定義的對象,那么就是在return之前調(diào)用析構(gòu)。
當(dāng)類的對象定義為全局變量時(全局區(qū)),會在main函數(shù)return函數(shù)返回之后和進(jìn)程結(jié)束之前,調(diào)用該對象的析構(gòu)函數(shù)。
析構(gòu)函數(shù)的作用
我們知道了析構(gòu)函數(shù)都是在類的對象生命周期結(jié)束時被調(diào)用,那么就代表下面不會再使用到這個對象;所以析構(gòu)函數(shù)一般用于一些收尾的工作,以防忘記。
比如當(dāng)你使用了該對象的成員申請了內(nèi)存(malloc、new等)、或者open了一些文件,那么可以在析構(gòu)函數(shù)中free delete 或者close。
例如:
#include <stdio.h>
#include <Windows.h>
struct Test
{
int x;
char* name;
Test()
{
name = (char*)malloc(sizeof(char)*20); // 構(gòu)造時動態(tài)申請
}
~Test()
{
if(this->name!=0) // 析構(gòu)時判斷是個否為空,不為空釋放
{
free(name);
name = 0;
}
}
};
int main()
{
Test te;
return 0;
}這里我就不運(yùn)行了,大家可以自己測試下。
總結(jié)
構(gòu)造函數(shù)
1、和類具有相同名稱,并且沒有返回值類型的函數(shù),就是類的構(gòu)造函數(shù)
2、構(gòu)造函數(shù)在定義對象的時候被調(diào)用
3、構(gòu)造函數(shù)可以進(jìn)行函數(shù)重載,可以有很多個
4、創(chuàng)建對象時默認(rèn)調(diào)用的是無參構(gòu)造
析構(gòu)函數(shù)
1、類的構(gòu)造函數(shù)名前加上'~'這個符號,就是類的析構(gòu)函數(shù)
2、析構(gòu)函數(shù)不能重載、不能有參數(shù)
3、析構(gòu)函數(shù)在變量聲明周期結(jié)束時被調(diào)用
4、析構(gòu)函數(shù)被調(diào)用分兩種情況:堆棧中定義的對象、全局區(qū)中定義的對象
到此這篇關(guān)于C++類的構(gòu)造與析構(gòu)特點及作用詳解的文章就介紹到這了,更多相關(guān)C++類的構(gòu)造與析構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++構(gòu)造析構(gòu)賦值運(yùn)算函數(shù)應(yīng)用詳解
- C++淺析構(gòu)造函數(shù)的特性
- C++類與對象深入之構(gòu)造函數(shù)與析構(gòu)函數(shù)詳解
- C++超詳細(xì)講解構(gòu)造函數(shù)與析構(gòu)函數(shù)的用法及實現(xiàn)
- C++分析類的對象作類成員調(diào)用構(gòu)造與析構(gòu)函數(shù)及靜態(tài)成員
- C++分析構(gòu)造函數(shù)與析造函數(shù)的特點梳理
- 一起來學(xué)習(xí)C++的構(gòu)造和析構(gòu)
- C++繼承中的對象構(gòu)造與析構(gòu)和賦值重載詳解
- C++編程析構(gòu)函數(shù)拷貝構(gòu)造函數(shù)使用示例詳解
相關(guān)文章
基于WTL 雙緩沖(double buffer)繪圖的分析詳解
本篇文章是對WTL下使用雙緩沖(double buffer)繪圖進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Ubuntu 環(huán)境下的 C/C++ 編譯與調(diào)試配置方法
本文檔詳細(xì)介紹了如何在Ubuntu環(huán)境中使用VSCode進(jìn)行C/C++的編譯與調(diào)試配置,通過配置`tasks.json`和`launch.json`,實現(xiàn)了統(tǒng)一管理輸出文件、優(yōu)化調(diào)試流程以及跨平臺兼容性,配置了`g++`編譯器和`gdb`調(diào)試器,并使用C/C++插件來提高開發(fā)效率,感興趣的朋友跟隨小編一起看看吧2024-11-11
C語言使用普通循環(huán)方法和遞歸求斐波那契序列示例代碼
這篇文章主要介紹了C語言使用普通循環(huán)方法和遞歸求斐波那契序列示例代碼,大家參考使用吧2013-11-11
C語言實現(xiàn)BMP格式圖片轉(zhuǎn)化為灰度
這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)BMP格式圖片轉(zhuǎn)化為灰度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10

