直接上结论:
1、同一个类的所有对象,共用一个虚函数列表
2、父类和子类都分别有自己的虚函数列表数组
3、子类如果没有改写父类的虚函数,则父类和子类虚函数列表中的代表这个函数的那一项指向同一个函数。
图示:
测试代码及结论:
mytestclass.h:
#ifndef MYTESTCLASS_H
#define MYTESTCLASS_H
class MyTestClass
{
public:
int weight;
int age;
virtual void eat();
virtual void hh();
MyTestClass();
};
#endif // MYTESTCLASS_H
mytestclass.cpp:
#include "mytestclass.h"
#include "QDebug"
MyTestClass::MyTestClass()
{
}
void MyTestClass::eat()
{
qDebug() << "my eat";
}
void MyTestClass::hh()
{
qDebug() << "my hh";
}
mytestclass2.h
#ifndef MYTESTCLASS2_H
#define MYTESTCLASS2_H
#include "mytestclass.h"
class MyTestClass2 : public MyTestClass
{
public:
int weight2;
virtual void eat();
MyTestClass2();
};
#endif // MYTESTCLASS2_H
mytestclass2.cpp
#include "mytestclass2.h"
#include "QDebug"
MyTestClass2::MyTestClass2()
{
}
void MyTestClass2::eat()
{
qDebug() << "my2 eat";
}
main.cpp
#include "mytestclass.h"
#include "mytestclass2.h"
#include <QApplication>
typedef void(* fun_p)(void);
void Test_virtualFunc()
{
MyTestClass *pmyTestObj = new MyTestClass();
MyTestClass2 *pmyTestObj2 = new MyTestClass2();
MyTestClass2 *pmyTestObj3 = new MyTestClass2();
pmyTestObj->weight = 10;
pmyTestObj->age = 100;
pmyTestObj2->weight = 20;
pmyTestObj2->age = 200;
pmyTestObj2->weight2 = 2000;
pmyTestObj3->weight = 30;
pmyTestObj3->age = 300;
pmyTestObj3->weight2 = 3000;
fun_p **func_pp = (fun_p **)pmyTestObj;
fun_p **func_pp2 = (fun_p **)pmyTestObj2;
fun_p **func_pp3 = (fun_p **)pmyTestObj3;
(**func_pp)();
(**func_pp2)();
/* 父的地址空间 */
int *p = (int *)pmyTestObj;
qDebug() << "father: virtual list addr: " << (int *)*(int *)p;
p++;
qDebug() << "father: member1:" << *(int *)p;
p++;
qDebug() << "father: member2:" << *(int *)p;
/* 子1的地址空间 */
p = (int *)pmyTestObj2;
qDebug() << "son1: virtual list addr: " << (int *)*(int *)p;
p++;
qDebug() << "son1: member1:" << *(int *)p;
p++;
qDebug() << "son1: member1:" << *(int *)p;
p++;
qDebug() << "son1: member1:" << *(int *)p;
/* 子2的地址空间 */
p = (int *)pmyTestObj3;
qDebug() << "son2: virtual list addr: " << (int *)*(int *)p;
p++;
qDebug() << "son2: member1:" << *(int *)p;
p++;
qDebug() << "son2: member1:" << *(int *)p;
p++;
qDebug() << "son2: member1:" << *(int *)p;
/* 父虚函数列表存的内容 */
qDebug() << "father virtual Func1:" << (int *)((*func_pp)[0]);
qDebug() << "father virtual Func2:" << (int *)((*func_pp)[1]);
/* 子1虚函数列表存的内容 */
qDebug() << "son1 virtual Func1:" << (int *)((*func_pp2)[0]);
qDebug() << "son1 virtual Func2:" << (int *)((*func_pp2)[1]);
/* 子2虚函数列表存的内容 */
qDebug() << "son2 virtual Func1:" << (int *)((*func_pp3)[0]);
qDebug() << "son2 virtual Func2:" << (int *)((*func_pp3)[1]);
}
int main(int argc, char *argv[])
{
Test_virtualFunc();
return 0;
}
测试结果:
my eat
my2 eat
father: virtual list addr: 0x409084
father: member1: 10
father: member2: 100
son1: virtual list addr: 0x409094
son1: member1: 20
son1: member1: 200
son1: member1: 2000
son2: virtual list addr: 0x409094
son2: member1: 30
son2: member1: 300
son2: member1: 3000
father virtual Func1: 0x4023d6
father virtual Func2: 0x402458
son1 virtual Func1: 0x4024fc
son1 virtual Func2: 0x402458
son2 virtual Func1: 0x4024fc
son2 virtual Func2: 0x402458