C++ 虚函数的调用机制的初步探索,vptr/vtbl究竟在何处,请看:(Solstice)
陈硕 2001-11-20 09:50:04 C++ 虚函数机制的初步探索 ———— 在单(且non-virtual)继承下的虚函数调用
我发现,在Borland C++ Builder Compiler free 5.5.1下
若Base pb = new Derived;
则pb == vptr, 且vtbl == *pb, 第一个虚函数的入口地址是vtbl[0], 第二个是vtbl[1], 等等
请看以下程序:
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
virtual void zuu() { cout << "Base::zuu" << endl; }
virtual void foo() { cout << "Base::foo " << ", a = " << a <<endl; }
virtual void gaa(int c) { cout << "Base::gaa"<< ", a = " << a << ", c = " << c << endl; }
Base():a(123) { };
protected:
int a;
};
class Derived : public Base
{
public:
virtual void zuu(){ cout << "Derived::zuu" << endl; }
virtual void foo() { cout << "Derived::foo " << ", a = " << a << ", b = " << b << endl; }
Derived():b(456) { };
private:
int b;
};
void mycall_noPara(void *p, int n);
void mycall_int(void *p, int n, int para);
int main()
{
Base *pb = new Derived;
cout << "Derived object: \n";
pb->zuu(); //没有访问data member
pb->foo(); //访问data member
pb->gaa(1982); //访问datamember和argument
cout << "\nDirectly invoke the virtual functions : \n" ;
mycall_noPara(pb, 0);
mycall_noPara(pb, 1);
mycall_int(pb, 2, 1982);
delete pb;
pb = new Base;
cout << "\n\nBase object: \n";
pb->zuu();
pb->foo();
pb->gaa(1982);
cout << "\nDirectly invoke the virtual functions : \n" ;
mycall_noPara(pb, 0);
mycall_noPara(pb, 1);
mycall_int(pb, 2, 1982);
delete pb;
}
void mycall_noPara(void *vptr, int n)
{
typedef void (*VTBL)(); // Virtual Table
typedef void (*PFV)(void*); // Pointer to Function with parameter (void*)
VTBL *vtbl = (VTBL*)*(int*)vptr; // dereference the vptr, initialize vtbl
PFV pfv = (PFV)vtbl[n]; // 得到第n个 Virtual Function's address
pfv(vptr); // consider p as the "this" pointer, invoke the function
}
void mycall_int(void *vptr, int n, int para)
{
typedef void (*VTBL)();
typedef void (*PFVI)(void*, int); // Pointer to Function with parameter (void*, int)
VTBL *vtbl = (VTBL*)*(int*)vptr; // dereference the vptr, initialize vtbl
PFVI pfvi = (PFVI)vtbl[n]; // 得到第n个 Virtual Function's address //小弟英语不够好
pfvi(vptr, para); // consider p as the "this" pointer, invoke the function
}
侯先生在《C++ 的沉迷与爱恋》一文中的建议:
----- 引用 -----
●不要沉迷於 C++ semantics 和 C++ object model
对於底层知识有浓厚兴趣的朋友,下探到 object model 领域,一定会非常开心地在 object size、object layout、vptr/vtbl、以及许多布幕後的技术之间玩将起来。了解这些东西,当然是好的,但是由於一探究竟得其奥秘的快感与成就感,使得一些朋友们在这个层面里「玩」起来了,小地方玩得很精,玩得不亦乐乎,玩得忽略了 C++/OOP 的最终目标。
最终目标是 polymorphism!
我要说,在 C++ syntax 以及相对低阶的 C++ semantics 里,不要玩得太过火。过犹不及,会伤身的。
----- 引用完 -----
牢记侯Sir的教导!