在C++中,虛函數(shù)的調(diào)用是通過虛指針(vptr)和虛表(vtable)來實現(xiàn)的。當一個類含有虛函數(shù)時,編譯器會為這個類創(chuàng)建一個虛表,虛表中存放著虛函數(shù)的地址。同時,編譯器會在類的實例中添加一個指向虛表的指針(vptr)。當調(diào)用虛函數(shù)時,程序會通過對象的vptr找到虛表,然后在虛表中查找并調(diào)用相應的虛函數(shù)。
以下是虛函數(shù)調(diào)用的實現(xiàn)過程:
編譯器為每個包含虛函數(shù)的類創(chuàng)建一個虛表(vtable)。虛表中存放著虛函數(shù)的地址,按照虛函數(shù)在類中的聲明順序排列。
編譯器在類的實例中添加一個指向虛表的指針(vptr)。vptr通常位于對象實例的內(nèi)存布局的開始位置,這樣可以保證訪問vptr的代價最小。
當調(diào)用虛函數(shù)時,首先通過對象的vptr找到虛表。然后在虛表中根據(jù)虛函數(shù)的索引(即在類中聲明的順序)查找到虛函數(shù)的地址。最后,調(diào)用找到的虛函數(shù)。
以下是一個簡單的示例,展示了虛函數(shù)調(diào)用的實現(xiàn)過程:
#include<iostream>
class Base {
public:
virtual void foo() {
std::cout << "Base::foo()"<< std::endl;
}
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Derived::foo()"<< std::endl;
}
};
int main() {
Base* base_ptr = new Derived();
base_ptr->foo(); // 輸出 "Derived::foo()"
delete base_ptr;
return 0;
}
在這個示例中,Base
類包含一個虛函數(shù)foo()
,Derived
類重寫了這個虛函數(shù)。當我們通過Base
類的指針調(diào)用foo()
時,程序會通過base_ptr
的vptr找到Derived
類的虛表,然后在虛表中查找并調(diào)用Derived::foo()
。