朱金灿 《深入浅出MFC》在第二章中说:虚函数表的内容是依据类中的虚函数声明次序,一一填入函数指针。派生类会继承基类的虚函数表(以及其它可以继承的成员),当 我们在派生类中改写虚函数时,虚函数表就受了影响:表中元素所指的函数地址 将不再是基类的函数地址,而是派生类的函数地址。 测试程序: #include <iostream.h>#include <stdio.h>class ClassA{public:int m_data1;int m_data2;void func1() { }void func2() { }virtual void vfunc1() { }virtual void vfunc2() { }};class ClassB : public ClassA{public:int m_data3;void func2() { }virtual void vfunc1() { }};class ClassC : public ClassB{public:int m_data1;int m_data4;void func2() { }virtual void vfunc1() { }}; void main(){cout << sizeof(ClassA) << endl;cout << sizeof(ClassB) << endl;cout << sizeof(ClassC) << endl;ClassA a;ClassB b;ClassC c;b.m_data1 = 1;b.m_data2 = 2;b.m_data3 = 3;c.m_data1 = 11;c.m_data2 = 22;c.m_data3 = 33;c.m_data4 = 44;c.ClassA::m_data1 = 111;cout << b.m_data1 << endl;cout << b.m_data2 << endl;cout << b.m_data3 << endl;cout << c.m_data1 << endl;cout << c.m_data2 << endl;cout << c.m_data3 << endl;cout << c.m_data4 << endl;cout << c.ClassA::m_data1 << endl;cout << &b << endl;cout << &(b.m_data1) << endl;cout << &(b.m_data2) << endl;cout << &(b.m_data3) << endl;cout << &c << endl;cout << &(c.m_data1) << endl;cout << &(c.m_data2) << endl;cout << &(c.m_data3) << endl;cout << &(c.m_data4) << endl;cout << &(c.ClassA::m_data1) << endl;} 执行结果是:1216241231122331110X0064FDCC0X0064FDD00X0064FDD40X0064FDD80X0064FDB00X0064FDC00X0064FDB80X0064FDBC0X0064FDC40X0064FDB4 我在想这个例子能说明问题吗?不能说明问题。我觉得应该这样才能说明问 题:不是说假如派生类中改写虚函数时,虚函数表就受了影响:表中元素所指的 函数地址将不再是基类的函数地址,而是派生类的函数地址吗?那应该写两个程 序,一个是派生类中没有改写虚函数,然后比较派生类的虚函数表和基类的虚函 数表看函数地址有没有变化;另一个是派生类中改写了虚函数,然后比较派生类 的虚函数表和基类的虚函数表,看函数地址有没有变化。 下面是我的证明程序:// 虚函数.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <stdio.h> #include <iostream.h> void DispVFT(DWORD* pVFT) { printf("VFT Pointer:%p\n" , pVFT); printf("Begin\n"); DWORD* p = (DWORD* )*pVFT;//得到VFT的首址 while(*p) { printf("VF:%p , %p\n", p , *p); p++; } printf("End\n\n"); } class A { public: A() { printf("in A\n"); DispVFT((DWORD*)this); } ~A(){} void fun() { cout<<"A::fun\n"; } virtual void vfun() { cout<<"A::vfun\n"; } }; class B:public A { public: B() { printf("in B\n"); DispVFT((DWORD*)this); } ~B(){} void fun() { cout<<"B::fun\n"; } virtual void vfun() { cout<<"B::vfun\n"; } virtual void vfun2() { cout<<"B::vfun2\n"; } }; void test(A* p) { p->fun(); p->vfun(); } int main(int argc, char* argv[]) { A a; B b; // test(&a); test(&b); return 0; } 上面是改变了虚函数的例子,你会发现虚函数的地址确实改变了,但是如果把类b的改写虚函数的部分去掉,你会发现类b的虚函数地址并没有改变。

评论