最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中析構(gòu)函數(shù)為何是虛函數(shù)

 更新時間:2022年11月25日 14:54:52   作者:The Laughing Uncle  
這篇文章主要介紹了C++中析構(gòu)函數(shù)為何是虛函數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

析構(gòu)函數(shù)為什么是虛函數(shù)

虛構(gòu)函數(shù)是虛函數(shù)的情況只需要在特定場景下出現(xiàn)即可,正常情況下不必要弄成虛函數(shù)。

如果基類的析構(gòu)函數(shù)不是虛函數(shù),在特定情況下會導(dǎo)致派生來無法被析構(gòu)。

  • 情況1:用派生類類型指針綁定派生類實例,析構(gòu)的時候,不管基類析構(gòu)函數(shù)是不是虛函數(shù),都會正常析構(gòu)
  • 情況2:用基類類型指針綁定派生類實例,析構(gòu)的時候,如果基類析構(gòu)函數(shù)不是虛函數(shù),則只會析構(gòu)基類,不會析構(gòu)派生類對象,從而造成內(nèi)存泄漏。為什么???因為析構(gòu)的時候如果沒有虛函數(shù)的動態(tài)綁定功能,就只根據(jù)指針的類型來進(jìn)行的,而不是根據(jù)指針綁定的對象來進(jìn)行,所以只是調(diào)用了基類的析構(gòu)函數(shù);如果基類的析構(gòu)函數(shù)是虛函數(shù),則析構(gòu)的時候就要根據(jù)指針綁定的對象來調(diào)用對應(yīng)的析構(gòu)函數(shù)了。

構(gòu)造函數(shù)為什么不能出虛函數(shù)

因為類的虛函數(shù)表指針是在構(gòu)造函數(shù)中初始化的,這時候如果構(gòu)造函數(shù)本身是虛函數(shù),又應(yīng)該由誰來初始化它的虛函數(shù)指針呢,所以構(gòu)造函數(shù)不能是虛函數(shù)。

為什么構(gòu)造函數(shù)和析構(gòu)函數(shù)都不能調(diào)用虛函數(shù)

?? ?#include <iostream.h>

? ? using namespace std;

? ? class Base{
? ? ? ? public:
? ? ? ? ? ? Base(){
? ? ? ? ? ? ? ? cout << "Base::Base()\n";
? ? ? ? ? ? ? ? fun();
? ? ? ? ? ? }
? ? ? ? ? ? virtual ~Base(){
? ? ? ? ? ? ? ? cout << "Base::Base()\n";
? ? ? ? ? ? ? ? fun();
? ? ? ? ? ? }
? ? ? ? ? ? virtual void fun(){
? ? ? ? ? ? ? ? cout << "Base::fun() virtual\n";
? ? ? ? ? ? }
? ? };

? ? // 派生類
? ? class Derive: public Base{
? ? ? ? public:
? ? ? ? ? ? Derive(){
? ? ? ? ? ? ? ? cout << "Derive::Derive()\n";
? ? ? ? ? ? ? ? fun();
? ? ? ? ? ? }
? ? ? ? ? ? ~Derive(){
? ? ? ? ? ? ? ? cout << "Derive::Derive()\n";
? ? ? ? ? ? ? ? fun();
? ? ? ? ? ? }
? ? ? ? ? ? virtual void fun(){
? ? ? ? ? ? ? ? cout << "Derive::fun() virtual\n";
? ? ? ? ? ? }
? ? };

? ? int main()
? ? {
? ? ? ? Base *bd = new Derive(); ?// 基類Base的指針bd指向的是派生類Derive的對象
? ? ? ? delete bd;
? ? ? ? return 0;
? ? }

對于上述情況,基類指針指向派生類對象。構(gòu)造時,先調(diào)用基類Base的構(gòu)造函數(shù),此時構(gòu)函數(shù)中調(diào)用基類中的fun()函數(shù),此時虛函數(shù)的動態(tài)綁定機(jī)制并沒有會生效,這是因為此時的派生類還不存在。析構(gòu)時,先析構(gòu)派生類,派生類中的fun()函數(shù)調(diào)用的是自己的fun(),然后析構(gòu)基類Base,基類析構(gòu)函數(shù)中的fun()調(diào)用的是基類Base自己的fun()函數(shù),這里虛函數(shù)的動態(tài)綁定機(jī)制也沒有生效,因為此時派生類已經(jīng)不存在了。

不要在構(gòu)造函數(shù)中調(diào)用虛函數(shù)的原因:因為父類對象會在子類之前進(jìn)行構(gòu)造,此時子類部分的數(shù)據(jù)成員還未初始化, 因此調(diào)用子類的虛函數(shù)是不安全的,故而C++不會進(jìn)行動態(tài)聯(lián)編。

不要在析構(gòu)函數(shù)中調(diào)用虛函數(shù)的原因:析構(gòu)函數(shù)是用來銷毀一個對象的,在銷毀一個對象時,先調(diào)用子類的析構(gòu)函數(shù),然后再調(diào)用基類的析構(gòu)函數(shù)。所以在調(diào)用基類的析構(gòu)函數(shù)時,派生類對象的數(shù)據(jù)成員已經(jīng)“銷毀”,這個時再調(diào)用子類的虛函數(shù)已經(jīng)沒有意義了。

c++基類的析構(gòu)函數(shù)為虛函數(shù)的原因

原因

在實現(xiàn)多態(tài)時, 當(dāng)用基類指針操作派生類, 在析構(gòu)時候防止只析構(gòu)基類而不析構(gòu)派生類。

例子

(1): 

#include<iostream>
  using namespace std;
  class Base{
  public:
?   ?Base() {};
  ? ~Base() {cout << "Output from the destructor of class Base!" << endl;};
?
  ? void DoSomething() { cout << "Do something in class Base!" << endl; };
  };
?
  class Derived : public Base{
  public:
?   ?Derived() {};
  ? ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };
?
  ? void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
? int ?main()
? ?{?
?    Derived* p = new Derived;
    ?p->DoSomething();
    ?delete p;
    ?return 0;
  }

運(yùn)行結(jié)果:

Do something in class Derived!           

Output from the destructor of class Derived!

Output from the destructor of class Base! 

代碼中基類的析構(gòu)函數(shù)不是虛函數(shù),在main函數(shù)中用繼承類的指針去操作繼承類的成員,釋放指針P的過程是:先釋放繼承類的資源,再釋放基類資源。

(2):

 ?#include<iostream>
  using namespace std;
  class Base{
  public:
?   ?Base() {};
  ? ~Base() {cout << "Output from the destructor of class Base!" << endl;};
?
  ? void DoSomething() { cout << "Do something in class Base!" << endl; };
  };
  class Derived : public Base{
  public:
?   ?Derived() {};
  ? ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };
?
  ? void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
? int ?main(){?
?    Base* p = new Derived;
    ?p->DoSomething();
    ?delete p;
    ?return 0;
  ?}

運(yùn)行結(jié)果:

Do something in class ClxBase!
Output from the destructor of class ClxBase!

代碼中基類的析構(gòu)函數(shù)同樣不是虛函數(shù),不同的是在main函數(shù)中用基類的指針去操作繼承類的成員,釋放指針P的過程是:只釋放基類的資源,而沒有調(diào)用繼承類的析構(gòu)函數(shù)。 調(diào)用DoSomething()函數(shù)執(zhí)行的也是基類定義的函數(shù)。

一般情況下,這樣的刪除只能夠刪除基類對象,而不能刪除子類對象,形成了刪除一半形象,造成內(nèi)存泄漏。

在公有繼承中,基類對派生類及其對象的操作,只能影響到那些從基類繼承下來的成員。如果想要用基類對非繼承成員進(jìn)行操作,則要把基類的這個函數(shù)定義為虛函數(shù)。 析構(gòu)函數(shù)自然也應(yīng)該如此:如果它想析構(gòu)子類中的重新定義或新的成員及對象,當(dāng)然也應(yīng)該聲明為虛的。

(3): 

#include<iostream>
  using namespace std;
  class Base{
  public:
?   ?Base() {};
  ? virtual ~Base() {cout << "Output from the destructor of class Base!" << endl;};
?
  ? virtual void DoSomething() { cout << "Do something in class Base!" << endl; };
  };
  class Derived : public Base{
  public:
?   ?Derived() {};
  ? ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };
?
  ? void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
? int ?main(){?
?    Base* p = new Derived;
    ?p->DoSomething();
    ?delete p;
    ?return 0;
  ?}

運(yùn)行結(jié)果:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
Output from the destructor of class ClxBase!

代碼中基類的析構(gòu)函數(shù)被定義為虛函數(shù),在main函數(shù)中用基類的指針去操作繼承類的成員,釋放指針P的過程是:釋放了繼承類的資源,再調(diào)用基類的析構(gòu)函數(shù)。調(diào)用DoSomething()函數(shù)執(zhí)行的也是繼承類定義的函數(shù)。

小結(jié):基類指針可以指向派生類的對象(多態(tài)性),如果刪除該指針delete p;就會調(diào)用該指針指向的派生類析構(gòu)函數(shù),而派生類的析構(gòu)函數(shù)又自動調(diào)用基類的析構(gòu)函數(shù),這樣整個派生類的對象完全被釋放。

如果析構(gòu)函數(shù)不被聲明成虛函數(shù),則編譯器實施靜態(tài)綁定,在刪除基類指針時,只會調(diào)用基類的析構(gòu)函數(shù)而不調(diào)用派生類析構(gòu)函數(shù),這樣就會造成派生類對象析構(gòu)不完全。所以,將析構(gòu)函數(shù)聲明為虛函數(shù)是十分必要的。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Visual Studio 2022卡死分析

    Visual Studio 2022卡死分析

    本文主要介紹了Visual Studio 2022卡死分析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • C++中的取余函數(shù)remainder與fmod詳解

    C++中的取余函數(shù)remainder與fmod詳解

    這篇文章主要為大家詳細(xì)介紹了C++中的取余函數(shù)remainder、fmod的具體使用以及自編的remainder及fmod,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)
    2023-05-05
  • C++調(diào)用Go方法的字符串傳遞問題及解決方案

    C++調(diào)用Go方法的字符串傳遞問題及解決方案

    這篇文章主要介紹了C++調(diào)用Go方法的字符串傳遞問題及解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • C語言對堆排序一個算法思路和實現(xiàn)代碼

    C語言對堆排序一個算法思路和實現(xiàn)代碼

    這篇文章主要介紹了C語言對堆排序一個算法思路和實現(xiàn)代碼,堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進(jìn),需要的朋友可以參考下
    2014-06-06
  • C++ std::function的用法詳解

    C++ std::function的用法詳解

    這篇文章主要介紹了C++ std::function使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • c++ 如何在libuv中實現(xiàn)tcp服務(wù)器

    c++ 如何在libuv中實現(xiàn)tcp服務(wù)器

    這篇文章主要介紹了c++ 如何在libuv中實現(xiàn)tcp服務(wù)器,幫助大家更好的理解和使用libuv,感興趣的朋友可以了解下
    2021-02-02
  • C/C++函數(shù)參數(shù)聲明解析int?fun()?與?int?fun(void)?的區(qū)別講解

    C/C++函數(shù)參數(shù)聲明解析int?fun()?與?int?fun(void)?的區(qū)別講解

    C++中int fun()和int fun(void)的區(qū)別在于函數(shù)參數(shù)的聲明方式,前者默認(rèn)允許任意參數(shù),而后者表示沒有參數(shù),通過清晰的實例源代碼,詳細(xì)解釋了它們在函數(shù)聲明和調(diào)用中的不同之處,這篇文章介紹了C/C++函數(shù)參數(shù)聲明int?fun()與int?fun(void)的差異,需要的朋友可以參考下
    2024-01-01
  • C++設(shè)計模式迪米特法則實例

    C++設(shè)計模式迪米特法則實例

    這篇文章主要為大家詳細(xì)介紹了C++設(shè)計模式迪米特法則實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-12-12
  • C++如何調(diào)用已經(jīng)寫好的C接口

    C++如何調(diào)用已經(jīng)寫好的C接口

    如何在C++代碼中調(diào)用寫好的C接口?你可能會奇怪,C++不是兼容C嗎?直接調(diào)用不就可以了,那么我們來測試一下,先看看C++如何調(diào)用C代碼接口的,需要的朋友可以參考一下
    2021-10-10
  • 如何讓Dev-C++支持auto關(guān)鍵字呢

    如何讓Dev-C++支持auto關(guān)鍵字呢

    這篇文章主要介紹了如何讓Dev-C++支持auto關(guān)鍵字問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

盈江县| 沽源县| 弥渡县| 囊谦县| 巧家县| 尚义县| 延长县| 肃宁县| 九寨沟县| 文化| 苍溪县| 绥阳县| 当涂县| 磴口县| 合山市| 库伦旗| 大足县| 闽清县| 江安县| 阿拉善右旗| 长兴县| 江北区| 通化市| 灵宝市| 瑞丽市| 新闻| 肥东县| 仲巴县| 台前县| 习水县| 新竹市| 沾化县| 合川市| 昌宁县| 张掖市| 山东| 阳泉市| 桦川县| 祁东县| 汝南县| 宁远县|