C++中虛表是什么意思(概念及示例)
虛函數(shù)表,以及虛函數(shù)指針是實(shí)現(xiàn)多態(tài)性(Polymorphism)的關(guān)鍵機(jī)制。多態(tài)性允許我們通過基類的指針或引用來調(diào)用派生類的函數(shù)
定義
虛函數(shù)(Virtual Function)
定義:類中使用virtual 關(guān)鍵字修飾的函數(shù) 叫做虛函數(shù)
語法:
highlighter- cpp
class Base {
public:
virtual void show() { cout << "Base show" << endl; }
};虛函數(shù)表(Virtual Function Table)
- 定義:當(dāng)類含有至少一個(gè)虛函數(shù)時(shí),編譯器會(huì)為該類創(chuàng)建一個(gè)虛函數(shù)表。這個(gè)表是一個(gè)編譯時(shí)構(gòu)建的靜態(tài)數(shù)組,存儲(chǔ)了指向類中所有虛函數(shù)的指針。如果一個(gè)派生類重寫了這些函數(shù),那么在派生類的虛表中,相應(yīng)函數(shù)的指針會(huì)被更新為指向派生類中的版本。
- 作用:v-table使得在運(yùn)行時(shí)可以實(shí)現(xiàn)函數(shù)的動(dòng)態(tài)綁定,允許通過基類的指針或引用調(diào)用正確的函數(shù)版本。
虛函數(shù)指針(Virtual Pointer)
- 定義:每個(gè)含有虛函數(shù)的類的對(duì)象(實(shí)例化出的)會(huì)持有一個(gè)指向相應(yīng)虛表的指針,這個(gè)指針通常被稱為虛指針(vptr)。vptr是對(duì)象運(yùn)行時(shí)的一部分,確保了當(dāng)通過基類指針調(diào)用虛函數(shù)時(shí),能夠查找到正確的函數(shù)實(shí)現(xiàn)。
- 作用:在對(duì)象的生命周期開始時(shí),構(gòu)造函數(shù)會(huì)設(shè)置vptr以指向相應(yīng)的虛函數(shù)表。如果有派生類對(duì)象,它的構(gòu)造函數(shù)會(huì)更新vptr,以指向派生類的虛函數(shù)表。這保證了通過基類的引用或指針調(diào)用虛函數(shù)也會(huì)執(zhí)行最派生類的重寫版本。
示例
highlighter- cpp
#include <iostream>
using namespace std;
class Base {
public:
virtual void func1() { cout << "Base::func1" << endl; }
virtual void func2() { cout << "Base::func2" << endl; }
};
class Derived : public Base {
public:
void func1() override { cout << "Derived::func1" << endl; }
// func2() 繼承自 Base
};
void printVTable(void* obj) {
cout << "vptr Address: " << obj << endl;
void** vTable = *(void***)obj;
cout << "VTable[0] (func1): " << vTable[0] << endl;
cout << "VTable[1] (func2): " << vTable[1] << endl;
}
int main() {
Base* base = new Base();
Derived* derived = new Derived();
cout << "Base object:" << endl;
printVTable(base);
cout << "\nDerived object:" << endl;
printVTable(derived);
delete base;
delete derived;
return 0;
}程序輸出如下,可以看到?jīng)]用重寫的func2函數(shù)地址是一樣的。
highlighter- apache
Base object: vptr Address: 0x8c1510 VTable[0] (func1): 0x422270 VTable[1] (func2): 0x4222b0 Derived object: vptr Address: 0x8c1530 VTable[0] (func1): 0x422330 VTable[1] (func2): 0x4222b0
如下圖所示:

面試題
(來自2024騰訊實(shí)習(xí)面試)場(chǎng)景題:一個(gè)類 A,里面有一個(gè)打印 helloworld 的虛函數(shù),然后類 A 會(huì)在構(gòu)造函數(shù)里調(diào)用這個(gè)虛函數(shù),此時(shí)有個(gè)類 B,繼承A,重寫了這個(gè) helloworld虛函數(shù),問你在創(chuàng)建類 B 時(shí),會(huì)打印 A 里的 helloworld 還是 B 里的。
代碼如下:
highlighter- arduino
class A {
public:
A() {
print();
}
virtual void print() {
cout << "A print" << endl;
}
};
class B : public A {
public:
void print() override {
cout << "B print" << endl;
}
};
int main() {
A* aTemp = new B();
delete aTemp;
}解答:基類構(gòu)造函數(shù)執(zhí)行的時(shí)候,派生類的部分尚未初始化,因此調(diào)用的虛函數(shù)不會(huì)下發(fā)到派生類中。
最終會(huì)打印 A print,而不是類 B 里重寫的版本
到此這篇關(guān)于C++中虛表是什么的文章就介紹到這了,更多相關(guān)C++虛表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Qt實(shí)現(xiàn)定時(shí)器的兩種方法分享
這篇文章主要為大家詳細(xì)介紹了Qt中實(shí)現(xiàn)定時(shí)器的兩種不同方法,文中的示例代碼講解詳細(xì),對(duì)我們了解Qt有一定的幫助,感興趣的可以跟隨小編一起學(xué)習(xí)一下2022-11-11
C++結(jié)合OpenCV實(shí)現(xiàn)RRT算法(路徑規(guī)劃算法)
這篇文章主要介紹了C++結(jié)合OpenCV實(shí)現(xiàn)RRT算法,RRT算法整體框架主要分為rand、near、new三點(diǎn)的建立和near與new之間的安全性檢查,需要的朋友可以參考下2022-05-05
C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型
這篇文章主要介紹了C/C++程序開發(fā)中實(shí)現(xiàn)信息隱藏的三種類型的相關(guān)資料,需要的朋友可以參考下2016-02-02
QT基于TCP實(shí)現(xiàn)文件傳輸系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了QT基于TCP實(shí)現(xiàn)文件傳輸系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08

