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

C++虛函數(shù)表和虛析構(gòu)介紹

 更新時(shí)間:2021年11月12日 10:39:57   作者:學(xué)渣的C/C++  
這篇文章主要介紹了C++虛函數(shù)表和虛析構(gòu),虛函數(shù)表是C++實(shí)現(xiàn)多態(tài)的基礎(chǔ),多態(tài)是面向?qū)ο蟮娜筇匦灾?,下面文章我們一起?lái)看看詳細(xì)內(nèi)容,需要的朋友可以參考一下

1、虛函數(shù)表

虛函數(shù)表是C++實(shí)現(xiàn)多態(tài)的基礎(chǔ),多態(tài)是面向?qū)ο蟮娜筇匦灾唬鄳B(tài)有利于提高代碼的可讀性,便于后期代碼的擴(kuò)展和維護(hù)。我們都知道多態(tài)的實(shí)現(xiàn)是基于虛函數(shù)表,那么虛函數(shù)表是什么時(shí)候創(chuàng)建的呢?虛函數(shù)表是怎么實(shí)現(xiàn)多態(tài)的功能的呢?

首先應(yīng)該明確多態(tài)也稱(chēng)為動(dòng)態(tài)多態(tài),他是在程序運(yùn)行時(shí)候確定函數(shù)地址的,也就是程序在運(yùn)行時(shí),如果類(lèi)成員函數(shù)加了virtual關(guān)鍵字,就會(huì)建立一個(gè)虛函數(shù)指針(vfptr)指針指向一個(gè)虛函數(shù)表,這個(gè)虛函數(shù)表就保存了虛函數(shù)的地址,子類(lèi)繼承父類(lèi)也自然繼承了虛函數(shù)指針,當(dāng)子類(lèi)重寫(xiě)父類(lèi)的虛函數(shù)時(shí),虛函數(shù)指針?biāo)赶虻奶摵瘮?shù)表中的虛函數(shù)地址就會(huì)被覆蓋,替換成子類(lèi)的虛函數(shù)地址。也就是通過(guò)父類(lèi)的虛函數(shù)指針找到了子類(lèi)的虛函數(shù)地址,進(jìn)而執(zhí)行這個(gè)函數(shù)。

下面我們通過(guò)代碼進(jìn)行詳細(xì)說(shuō)明:

#include <iostream>
using namespace std;

class Base{
public:
    void func(){
        cout << "Base func" << endl;
    }
};

class Son: public Base{
    void func(){
        cout << "Son func" << endl;
    }
};

void test(Base& base) {
    base.func();
}
int main () {
    Son son;

    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    cout << "sizeof(Son)  = " << sizeof(Son) << endl;   
    test(son);
    system("pause");
    return 0;

}

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

 因?yàn)楹瘮?shù)成員不占用類(lèi)的大小,所以對(duì)Base類(lèi)和Son類(lèi)輸出大小,都是一個(gè)字節(jié),這一個(gè)字節(jié)是為了可以實(shí)例化類(lèi),通過(guò)引用基類(lèi)引用派生類(lèi),調(diào)用func函數(shù),函數(shù)調(diào)用了基類(lèi)的func,那么如果我們加上virtual關(guān)鍵字后,就不是這種情況了。

#include <iostream>
using namespace std;

class Base{
public:
    virtual void func(){
        cout << "Base func" << endl;
    }
};

class Son: public Base{
    void func(){
        cout << "Son func" << endl;
    }
};


void test(Base& base) {
    base.func();
}
int main () {
    Son son;

    cout << "sizeof(Base) = " << sizeof(Base) << endl;
    cout << "sizeof(Son)  = " << sizeof(Son) << endl;   
    test(son);
    system("pause");
    return 0;

}

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

 可以看到加了virtual關(guān)鍵字后,父類(lèi)和子類(lèi)的大小都變成了四字節(jié),這是因?yàn)樯闪颂摵瘮?shù)指針,指針指向虛函數(shù)表,虛函數(shù)表存儲(chǔ)了虛函數(shù)地址,繼承了父類(lèi)的子類(lèi)重寫(xiě)了虛函數(shù),虛函數(shù)表中的函數(shù)地址被替換,再次調(diào)用虛函數(shù)就是調(diào)用了子類(lèi)的函數(shù)func。

2、虛析構(gòu)

虛析構(gòu)主要是為了解決子類(lèi)中有屬性開(kāi)辟到堆區(qū),父類(lèi)指針調(diào)用函數(shù)時(shí),無(wú)法調(diào)用到子類(lèi)的析構(gòu)代碼,導(dǎo)致子類(lèi)堆區(qū)內(nèi)存無(wú)法釋放。

首先我們看一下子類(lèi)堆區(qū)內(nèi)存開(kāi)辟,通過(guò)父類(lèi)指針來(lái)調(diào)用函數(shù),捕捉他們的構(gòu)造函數(shù)和析構(gòu)函數(shù)看下運(yùn)行結(jié)果:

#include <iostream>
using namespace std;

class Base{
public:
    Base(){
        cout << "Base 的構(gòu)造函數(shù)調(diào)用" << endl;
    }

    ~Base(){
        cout << "Base 的析構(gòu)函數(shù)調(diào)用" << endl;
    }
    virtual void func(){
        cout << "Base func" << endl;
    }
};

class Son: public Base{
public:
    Son(int val):m_val(new int (val)) {
        cout << "Son 的構(gòu)造函數(shù)調(diào)用" << endl;
    }

    ~Son(){
        cout << "Son 的析構(gòu)函數(shù)調(diào)用" << endl;
        if (m_val != NULL) {
            
            delete m_val;
            cout << "Son 析構(gòu)函數(shù)的堆內(nèi)存釋放" << endl;
            m_val = NULL;
        }
    }
    void func(){
        cout << "Son func" << endl;
    }

    void funcTest(){
        cout << "funcTest 函數(shù)調(diào)用" << endl;
    }

    int* m_val = NULL;
};


void test() {
   
    Base *base = new Son(10);
    base->func();
    //base->funcTest(); //無(wú)法調(diào)用,因?yàn)樘摵瘮?shù)表中不能找到這個(gè)函數(shù)的地址
    delete base;
    base = NULL;
}


int main () {
    test();    
    system("pause");
    return 0;

}

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

 可以明確,通過(guò)父類(lèi)指針來(lái)調(diào)用函數(shù)的時(shí)候,無(wú)法調(diào)用Son類(lèi)的析構(gòu)函數(shù),在Son類(lèi)在堆區(qū)上申請(qǐng)的內(nèi)存就無(wú)法釋放,造成內(nèi)存泄漏。Son類(lèi)的析構(gòu)函數(shù)不能調(diào)用的主要原因就是在虛函數(shù)表中找不到Son的析構(gòu)函數(shù)地址,解決辦法就是把Base類(lèi)的寫(xiě)成虛析構(gòu)函數(shù)或者純虛析構(gòu)函數(shù),

下面給出Base類(lèi)為純虛析構(gòu)函數(shù)的代碼和運(yùn)行結(jié)果:

#include <iostream>
using namespace std;

class Base{
public:
    Base(){
        cout << "Base 的構(gòu)造函數(shù)調(diào)用" << endl;
    }
    virtual ~Base() = 0;

    virtual void func(){
        cout << "Base func" << endl;
    }
};
    Base :: ~Base(){
        cout << "Base 的析構(gòu)函數(shù)調(diào)用" << endl;
    }

class Son: public Base{
public:
    Son(int val):m_val(new int (val)) {
        cout << "Son 的構(gòu)造函數(shù)調(diào)用" << endl;
    }

    ~Son(){
        cout << "Son 的析構(gòu)函數(shù)調(diào)用" << endl;
        if (m_val != NULL) {
            
            delete m_val;
            cout << "Son 析構(gòu)函數(shù)的堆內(nèi)存釋放" << endl;
            m_val = NULL;
        }
    }
    void func(){
        cout << "Son func" << endl;
    }

    void funcTest(){
        cout << "funcTest 函數(shù)調(diào)用" << endl;
    }

    int* m_val = NULL;
};


void test() {
   
    Base *base = new Son(10);
    base->func();
    //base->funcTest(); //無(wú)法調(diào)用,因?yàn)樘摵瘮?shù)表中不能找到這個(gè)函數(shù)的地址
    delete base;
    base = NULL;
}


int main () {
    test();    
    system("pause");
    return 0;

}

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

 可以看到只要把Base類(lèi)的析構(gòu)函數(shù)寫(xiě)成虛析構(gòu)函數(shù)或純虛析構(gòu)函數(shù),通過(guò)父類(lèi)指針調(diào)用函數(shù),子類(lèi)的析構(gòu)代碼會(huì)被調(diào)用,子類(lèi)堆區(qū)內(nèi)存得到釋放。

到此這篇關(guān)于C++虛函數(shù)表和虛析構(gòu)介紹的文章就介紹到這了,更多相關(guān)C++虛函數(shù)表和虛析構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中Boost的智能指針shared_ptr

    C++中Boost的智能指針shared_ptr

    這篇文章介紹了C++中Boost的智能指針shared_ptr,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • C++ Primer 第一部分基本語(yǔ)言

    C++ Primer 第一部分基本語(yǔ)言

    這篇文章主要介紹了C++ Primer 第一部分基本語(yǔ)言的相關(guān)資料,需要的朋友可以參考下
    2014-02-02
  • C++中結(jié)構(gòu)體和Json字符串互轉(zhuǎn)的問(wèn)題詳解

    C++中結(jié)構(gòu)體和Json字符串互轉(zhuǎn)的問(wèn)題詳解

    這篇文章主要給大家介紹了關(guān)于C++中結(jié)構(gòu)體和Json字符串互轉(zhuǎn)問(wèn)題的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C指針原理教程之垃圾回收-內(nèi)存泄露

    C指針原理教程之垃圾回收-內(nèi)存泄露

    C語(yǔ)言沒(méi)有運(yùn)行時(shí)庫(kù),無(wú)法自動(dòng)壓縮使用中的內(nèi)存,縮小堆棧所需內(nèi)存空間。若只申請(qǐng)內(nèi)存,沒(méi)有釋放,勢(shì)必造成系統(tǒng)內(nèi)存不斷減少、丟失。長(zhǎng)時(shí)間的運(yùn)行,最終導(dǎo)致系統(tǒng)死機(jī)。文章闡述了C語(yǔ)言垃圾產(chǎn)生的原因,并從引用計(jì)數(shù)、標(biāo)記一清除算法兩方面提出如何實(shí)現(xiàn)C語(yǔ)言的垃圾回收。
    2019-02-02
  • 解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題

    解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題

    今天小編就為大家分享一篇解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • C語(yǔ)言繪制曲線(xiàn)圖的示例代碼

    C語(yǔ)言繪制曲線(xiàn)圖的示例代碼

    這篇文章主要介為大家詳細(xì)紹了如何使用C語(yǔ)言繪制統(tǒng)計(jì)圖中的曲線(xiàn)圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話(huà)簿管理系統(tǒng)

    C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話(huà)簿管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言用函數(shù)實(shí)現(xiàn)電話(huà)簿管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++類(lèi)型轉(zhuǎn)換詳解

    C++類(lèi)型轉(zhuǎn)換詳解

    類(lèi)型轉(zhuǎn)換有c風(fēng)格的,當(dāng)然還有c++風(fēng)格的。c風(fēng)格的轉(zhuǎn)換的格式很簡(jiǎn)單(TYPE)EXPRESSION,但是c風(fēng)格的類(lèi)型轉(zhuǎn)換有不少的缺點(diǎn),有的時(shí)候用c風(fēng)格的轉(zhuǎn)換是不合適的,因?yàn)樗梢栽谌我忸?lèi)型之間轉(zhuǎn)換
    2021-10-10
  • 異步http listener 完全并發(fā)處理懲罰http懇求的小例子

    異步http listener 完全并發(fā)處理懲罰http懇求的小例子

    異步http listener 完全并發(fā)處理懲罰http懇求的小例子,需要的朋友可以參考一下
    2013-05-05
  • QT使用QComBox和QLineEdit實(shí)現(xiàn)模糊查詢(xún)功能

    QT使用QComBox和QLineEdit實(shí)現(xiàn)模糊查詢(xún)功能

    模糊查詢(xún)是指根據(jù)用戶(hù)輸入的文本,在下拉框的選項(xiàng)中進(jìn)行模糊匹配,并動(dòng)態(tài)地顯示匹配的選項(xiàng),本文將使用QComBox和QLineEdit實(shí)現(xiàn)模糊查詢(xún)功能,需要的可以參考下
    2023-11-11

最新評(píng)論

万安县| 九寨沟县| 原阳县| 塔河县| 五华县| 浦北县| 定日县| 武穴市| 临城县| 洛扎县| 阆中市| 五华县| 饶河县| 陆河县| 安庆市| 深泽县| 广丰县| 屏东市| 呈贡县| 云林县| 临颍县| 孟村| 手游| 屯门区| 三都| 偏关县| 永新县| 巩义市| 合江县| 中牟县| 新化县| 共和县| 嫩江县| 息烽县| 岳阳市| 东海县| 鄯善县| 高青县| 上虞市| 宁乡县| 都安|