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

C++虛函數(shù)表的使用小結(jié)

 更新時(shí)間:2026年02月08日 15:15:40   作者:yuanhao  
本文主要介紹了C++虛函數(shù)表的使用小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

使用過(guò)Java的同學(xué)應(yīng)該特別熟悉多態(tài),即耳熟能詳?shù)囊痪湓挘?strong>可以使用父類引用來(lái)指向子類對(duì)象,而實(shí)現(xiàn)起來(lái)非常容易,只需要重寫父類的方法或者實(shí)現(xiàn)接口的方法即可:

//Java代碼

class Parent {
    void show() {
        System.out.println("Inside Parent");
    }
}

class Child extends Parent {
    void show() {
        System.out.println("Inside Child");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.show(); // 調(diào)用的是子類的 show() 方法
    }
}

在Java中,這里是使用父類Parent的引用obj,指向了子類對(duì)象,然后調(diào)用的是子類的show()方法。

但是在C++中,如果按同樣類似的寫法,卻得到的結(jié)果不一樣:

//C++代碼

#include <iostream>

class Parent {
public:
    void show() {
        std::cout << "Inside Parent" << std::endl;
    }
};

class Child : public Parent {
public:
    void show() {
        std::cout << "Inside Child" << std::endl;
    }
};

int main() {
    Parent* obj = new Child();
    obj->show(); // 調(diào)用的是父類的 show() 方法
    delete obj;
    return 0;
}

在C++中,這里使用父類的指針,指向子類對(duì)象,但是最終調(diào)用的是父類的show()方法。那如何實(shí)現(xiàn)像Java那種效果呢?就需要使用虛函數(shù),本篇文章深入探究虛函數(shù)以及虛函數(shù)的原理--虛函數(shù)表(后面簡(jiǎn)稱虛表)的相關(guān)知識(shí)。

正文

關(guān)于虛函數(shù)的使用,以及純虛函數(shù)定義接口等,這些基礎(chǔ)知識(shí),暫時(shí)就不詳細(xì)說(shuō)明了,重點(diǎn)關(guān)注虛表。

虛表是屬于類

虛表是函數(shù)指針類型的數(shù)組,指向該類定義的虛函數(shù)。

在C++中,只要一個(gè)類包含了一個(gè)虛函數(shù),那么就有由一個(gè)虛表來(lái)維護(hù)。虛表是屬于類的,而非屬于某個(gè)對(duì)象,一個(gè)類只需要一個(gè)虛表,所以該類對(duì)象共用一個(gè)虛表。

當(dāng)類B繼承至類A,繼承類也可以調(diào)用A的函數(shù),如果A是一個(gè)包含虛表的基類,那么繼承類B也擁有自己的虛表。

理解類的虛表非常重要,比如有代碼:

class A {
public:
    A();
    virtual void vfunc1() { qDebug() << "A vfunc1()"; }
    virtual void vfunc2() { qDebug() << "A vfunc2()"; }
    void func1() { qDebug() << "A func1()"; }
    void func2() { qDebug() << "A func2()"; }

private:
    int m_data1, m_data2;
};

那么類A的虛表如圖:

虛表是一個(gè)指針數(shù)組,其元素是虛函數(shù)的指針,每個(gè)元素對(duì)應(yīng)一個(gè)虛函數(shù)的函數(shù)指針。非虛函數(shù)的函數(shù),調(diào)用不需要虛表,所以虛表中不會(huì)保存。虛表的創(chuàng)建在編譯時(shí)期,即在編譯時(shí)期,屬于一個(gè)類的虛表就構(gòu)造出來(lái)了。

對(duì)象的虛表指針

我們使用IDE調(diào)試模式,來(lái)看一下類A的對(duì)象包含哪些東西:

可以發(fā)現(xiàn)除了其數(shù)據(jù)成員外,還有一個(gè)__vptr指針,這個(gè)指針是虛表指針,指向類的虛表。為了指定對(duì)象的虛表,編譯器在類中添加了__vptr指針,專門用來(lái)指向虛表。

這里可以知道,同一個(gè)類的多個(gè)對(duì)象,其虛表指針?biāo)赶虻奶摫硎且粯拥模?/p>

效果如圖:

動(dòng)態(tài)綁定

重點(diǎn)來(lái)了,C++是如何通過(guò)虛表實(shí)現(xiàn)多態(tài)的,即動(dòng)態(tài)綁定,有如下3個(gè)類:

class A {
public:
    A();
    virtual void vfunc1() { qDebug() << "A vfunc1()"; }
    virtual void vfunc2() { qDebug() << "A vfunc2()"; }
    void func1() { qDebug() << "A func1()"; }
    void func2() { qDebug() << "A func2()"; }

private:
    int m_data1, m_data2;
};

class B : public A {
public:
    B();
    virtual void vfunc1() { qDebug() << "B vfunc1()"; }
    void func1() { qDebug() << "B func1()"; }

private:
    int m_data3;
};

class C : public B {
public:
    C();
    virtual void vfunc2() { qDebug() << "c vfunc2()"; }
    void func2() { qDebug() << "C func2()"; }

private:
        int m_data1, m_data4;
};

記?。?strong>虛表是屬于類的,上面代碼的虛表通過(guò)IDE調(diào)試模式如下:

虛表關(guān)系如圖:

我們來(lái)仔細(xì)分析:

  1. 類A包含2個(gè)虛函數(shù),所以A的虛表元素是2個(gè)。

  2. 類B繼承至A,但是重寫了虛函數(shù),對(duì)于重寫的虛函數(shù),會(huì)增加新的地址來(lái)保存新的函數(shù)指針。所以對(duì)于類B的虛表,有一個(gè)是繼承至A,即A::vfunc2*(),還有一個(gè)是新的函數(shù),即B::vfunc1()。

  3. 而對(duì)于C來(lái)說(shuō),它繼承至B,但是重寫了虛函數(shù),所以會(huì)多出一個(gè)C::vfunc2(),那么另一個(gè)虛函數(shù)指針是執(zhí)行類B的vfunc1()還是類A的vfunc1()呢?

    這里會(huì)指向B::vfunc1(),規(guī)律非常簡(jiǎn)單:對(duì)象的虛表指針用來(lái)指向類的虛表,虛表中的指針會(huì)指向其繼承的最近的一個(gè)類的虛函數(shù),所以C的虛表先是指向B的虛表,然后由于重寫虛函數(shù)的原因,會(huì)修改其中一個(gè)指針的值。

基類指針指向子類對(duì)象

搞明白上面的繼承關(guān)系后,多態(tài)就非常容易理解了,比如下面代碼:

B b;
A *p = &b;
p->vfunc1();

這里使用p來(lái)調(diào)用vfunc1(),最終會(huì)調(diào)用類B中的虛函數(shù),過(guò)程分析如下:

  1. 程序執(zhí)行p->vfunc1()時(shí),會(huì)發(fā)現(xiàn)p是一個(gè)指針,而且調(diào)用的是虛函數(shù)。
  2. 根據(jù)虛表指針p->__vptr來(lái)訪問(wèn)對(duì)象b對(duì)應(yīng)的虛表。雖然指針p是基類A的類型,但是__vptr也是基類的一部分,是編譯器加的,所以p->__ptr可以訪問(wèn)對(duì)象的虛表
  3. 虛表中查找調(diào)用的函數(shù),由于虛表是在編譯時(shí)就確定,所以p->vfunc1()根據(jù)上面的圖可知會(huì)調(diào)用B的虛函數(shù),即重寫的虛函數(shù)B::vfunc1()。

這個(gè)過(guò)程就是動(dòng)態(tài)綁定來(lái)實(shí)現(xiàn)的多態(tài),非常容易理解。

總結(jié)

什么情況下會(huì)發(fā)生動(dòng)態(tài)綁定呢?有如下幾個(gè)條件:

  1. 通過(guò)指針調(diào)用函數(shù)。
  2. 指針upcast向上轉(zhuǎn)型,比如繼承類向基類的轉(zhuǎn)換。
  3. 調(diào)用的是虛函數(shù)。

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

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼

    C語(yǔ)言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼

    本文主要介紹了C語(yǔ)言實(shí)現(xiàn)內(nèi)存函數(shù)的示例代碼,包括memcpy、memmove、memset和memcmp的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • C語(yǔ)言實(shí)現(xiàn)三子棋的示例代碼

    C語(yǔ)言實(shí)現(xiàn)三子棋的示例代碼

    所謂三子棋,就是三行三列的棋盤,玩家可以和電腦下棋,率先連成三個(gè)的獲勝。這篇文章主要為大家詳細(xì)介紹了如何通過(guò)C語(yǔ)言實(shí)現(xiàn)三子棋小游戲,感興趣的小伙伴可以嘗試一下
    2023-01-01
  • c++素?cái)?shù)篩選法

    c++素?cái)?shù)篩選法

    本文講的是篩選法的C++實(shí)現(xiàn), 篩選法又稱篩法,是求不超過(guò)自然數(shù)N(N&gt;1)的所有質(zhì)數(shù)的一種方法。據(jù)說(shuō)是古希臘的埃拉托斯特尼(Eratosthenes,約公元前274~194年)發(fā)明的,又稱埃拉托斯特尼篩子。
    2017-05-05
  • Qt中QByteArray?類型的使用詳解

    Qt中QByteArray?類型的使用詳解

    QByteArray是Qt中處理原始字節(jié)數(shù)據(jù)和8位字符串的核心容器類,本文就來(lái)詳解的介紹一下QByteArray?類型的使用,感興趣的可以了解一下
    2025-12-12
  • C++指針與引用的異同

    C++指針與引用的異同

    這篇文章主要介紹了C++指針與引用的異同,文章以C++指針與引用的相關(guān)資料結(jié)合指針和引用的相同點(diǎn)和區(qū)別展開詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • 基于c++的中國(guó)象棋游戲設(shè)計(jì)與實(shí)現(xiàn)

    基于c++的中國(guó)象棋游戲設(shè)計(jì)與實(shí)現(xiàn)

    這篇文章主要介紹了基于c++的中國(guó)象棋游戲設(shè)計(jì)與實(shí)現(xiàn),主要操作是possibleMove(int?x,?int?y),通過(guò)整個(gè)棋盤每個(gè)位置上的信息、中國(guó)象棋的規(guī)則來(lái)獲得位置(x,?y)這個(gè)棋子可以移動(dòng)到的位置,需要的朋友可以參考一下
    2022-02-02
  • C++實(shí)現(xiàn)八個(gè)常用的排序算法 插入排序、冒泡排序、選擇排序、希爾排序等

    C++實(shí)現(xiàn)八個(gè)常用的排序算法 插入排序、冒泡排序、選擇排序、希爾排序等

    這篇文章主要介紹了C++如何實(shí)現(xiàn)八個(gè)常用的排序算法:插入排序、冒泡排序、選擇排序、希爾排序 、快速排序、歸并排序、堆排序和LST基數(shù)排序,需要的朋友可以參考下
    2015-07-07
  • c++之類型別名的實(shí)現(xiàn)

    c++之類型別名的實(shí)現(xiàn)

    本文主要介紹了c++之類型別名的實(shí)現(xiàn),包括C++98版本使用typedef關(guān)鍵字和C++11版本推薦使用using關(guān)鍵字來(lái)創(chuàng)建類型別名,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-02-02
  • 老生常談C語(yǔ)言動(dòng)態(tài)函數(shù)庫(kù)的制作和使用(推薦)

    老生常談C語(yǔ)言動(dòng)態(tài)函數(shù)庫(kù)的制作和使用(推薦)

    下面小編就為大家?guī)?lái)一篇老生常談C語(yǔ)言動(dòng)態(tài)函數(shù)庫(kù)的制作和使用(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-08-08
  • C++實(shí)現(xiàn)二叉樹基本操作詳解

    C++實(shí)現(xiàn)二叉樹基本操作詳解

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)二叉樹基本操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12

最新評(píng)論

梅河口市| 新营市| 齐齐哈尔市| 华容县| 呼图壁县| 德保县| 中牟县| 莎车县| 远安县| 云阳县| 东城区| 富裕县| 阿城市| 仁化县| 旺苍县| 美姑县| 林周县| 大埔县| 辉县市| 丰都县| 龙山县| 天台县| 年辖:市辖区| 治县。| 萍乡市| 四平市| 北辰区| 和平区| 遵义县| 蒙城县| 临朐县| 阜新市| 子长县| 洛阳市| 正宁县| 阳江市| 宣武区| 永康市| 西乌| 兰考县| 壤塘县|