程序26.
| #include <iostream> using namespace std; class Base { public: Base() { cout << "In Base" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; cout << "Value at Vtable 3rd entry = " << (int*)*((int*)*(int*)this+2) << endl; cout << endl; } virtual void f1() { cout << "Base::f1" << endl; } virtual void f2() { cout << "Base::f2" << endl; } }; class Drive : public Base { public: Drive() { cout << "In Drive" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; cout << "Value at Vtable 3rd entry = " << (int*)*((int*)*(int*)this+2) << endl; cout << endl; } virtual void f1() { cout << "Drive::f1" << endl; } }; int main() { Drive d; return 0; } |
程序的输出为:
| In Base Virtual Pointer = 0012FF7C Address of Vtable = 0046C0E0 Value at Vtable 1st entry = 004010F0 Value at Vtable 2nd entry = 00401145 Value at Vtable 3rd entry = 00000000 In Drive Virtual Pointer = 0012FF7C Address of Vtable = 0046C0C8 Value at Vtable 1st entry = 0040121C Value at Vtable 2nd entry = 00401145 Value at Vtable 3rd entry = 00000000 |
这个程序的输出表明基类的虚函数在派生类中并未被重写,然后,派生类的构造函数没有对虚函数的入口做任何的事情。
那么现在,让我邀请纯虚函数来加入这一游戏,再来看看它的行为吧。请看以下的程序:
程序27.
| #include <iostream> using namespace std; class Base { public: Base() { cout << "In Base" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; cout << endl; } virtual void f1() = 0; virtual void f2() = 0; }; class Drive : public Base { public: Drive() { cout << "In Drive" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; cout << endl; } virtual void f1() { cout << "Drive::f1" << endl; } virtual void f2() { cout << "Drive::f2" << endl; } }; int main() { return 0; } |
在debug和release模式下,程序的输出有所不同。下面是debug模式的输出:
| In Base Virtual Pointer = 0012FF7C Address of Vtable = 0046C0BC Value at Vtable 1st entry = 00420CB0 Value at Vtable 2nd entry = 00420CB0 In Drive Virtual Pointer = 0012FF7C Address of Vtable = 0046C0A4 Value at Vtable 1st entry = 00401212 Value at Vtable 2nd entry = 0040128F |
以下则是release模式的输出:
| In Base Virtual Pointer = 0012FF80 Address of Vtable = 0042115C Value at Vtable 1st entry = 0041245D Value at Vtable 2nd entry = 0041245D In Drive Virtual Pointer = 0012FF80 Address of Vtable = 00421154 Value at Vtable 1st entry = 00401310 Value at Vtable 2nd entry = 00401380 |
为了更好地弄懂这一原理,我们需要对程序作少许的改动,并尝试使用函数指针来调用虚函数。
程序28.
| #include <iostream> using namespace std; typedef void(*Fun)(); class Base { public: Base() { cout << "In Base" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; // 尝试执行第一个虚函数 Fun pFun = (Fun)*((int*)*(int*)this+0); pFun(); cout << endl; } virtual void f1() = 0; virtual void f2() = 0; }; class Drive : public Base { public: Drive() { cout << "In Drive" << endl; cout << "Virtual Pointer = " << (int*)this << endl; cout << "Address of Vtable = " << (int*)*(int*)this << endl; cout << "Value at Vtable 1st entry = " << (int*)*((int*)*(int*)this+0) << endl; cout << "Value at Vtable 2nd entry = " << (int*)*((int*)*(int*)this+1) << endl; cout << endl; } virtual void f1() { cout << "Drive::f1" << endl; } virtual void f2() { cout << "Drive::f2" << endl; } }; int main() { Drive d; return 0; } |
现在程序的行为在debug和release模式下仍然不同。在debug模式下,它会显示一个运行时错误的对话框:
![]() |
并且,当你按下“忽略”按钮之后,它会显示下面的对话框:
![]() |
而在release模式下运行的话,它只会在控制台窗口中输出错误信息:
| In Base Virtual Pointer = 0012FF80 Address of Vtable = 0042115C Value at Vtable 1st entry = 0041245D Value at Vtable 2nd entry = 0041245D runtime error R6025 - pure virtual function call |

