文章目录
一、单继承的虚函数表
单继承的虚表是怎么样的呢?我们来看看下面单继承的代码再来分析
class Person
{
public:
virtual void fun1()
{
cout << "virtual void fun1() "<< endl;
}
virtual void fun2()
{
cout << "virtual void fun2()" << endl;
}
};
class Member :public Person
{
public:
virtual void fun1() //对fun1进行重写
{
cout << "virtual void fun1()" << endl;
}
virtual void fun3()
{
cout << "virtual void fun3() " << endl;
}
virtual void fun4()
{
cout << "virtual void fun4() " << endl;
}
};
int main()
{
Member m;
return 0;
}
调试窗口如下:
所以为了解决上面的几个疑问,我们不妨把虚表打印出来看看,代码实现如下:
class Person
{
public:
virtual void fun1()
{
cout << "virtual void fun1() "<< endl;
}
virtual void fun2()
{
cout << "virtual void fun2()" << endl;
}
};
class Member :public Person
{
public:
virtual void fun1()
{
cout << "virtual void fun1()" << endl;
}
virtual void fun3()
{
cout << "virtual void fun3() " << endl;
}
virtual void fun4()
{
cout << "virtual void fun4() " << endl;
}
};
typedef void(*VFptr)();
//对函数指针void(*)()类型起个名字叫VFptr
//所以下面使用VFptr就是void(*)()类型
//table为指向函数指针的指针,是一个二级指针
void PrintVFtable(VFptr* table)
{
for (int i=0; table[i] != nullptr; i++)
{
printf("[%d]:%p\n", i, table[i]);
VFptr f = table[i];
f();
}
}
int main()
{
Person p;
Member m;
//两种写法都行
//PrintVFtable((VFptr*)(*(int*)&m));
cout << "基类的虚函数为:" << endl;
PrintVFtable((VFptr*)(*(void**)&p));
cout << "派生类的虚函数为:" << endl;
PrintVFtable((VFptr*)(*(void**)&m));
return 0;
}
打印结果如下:
所以我们可以得出结论,子类的虚表中是存储子类的虚函数的,只不过编译器没有显示出来而已。
二、多继承的虚函数表
class A
{
public:
virtual void fun1()
{
cout << "class A::virtual void fun1()" << endl;
}
virtual void fun2()
{
cout << "class A::virtual void fun2()" << endl;
}
};
class B
{
public:
virtual void fun1()
{
cout << "vclass B::irtual void fun1()" << endl;
}
virtual void fun2()
{
cout << "class B::virtual void fun2()" << endl;
}
};
class C :public A,public B
{
public:
virtual void fun1()
{
cout << "class C::virtual void fun1()" << endl;
}
virtual void fun3()
{
cout << "class C::virtual void fun3()" << endl;
}
};
typedef void(*VFptr)();
//对函数指针void(*)()类型起个名字叫VFptr
//所以下面使用VFptr就是void(*)()类型
//table为指向函数指针的指针,是一个二级指针
void PrintVFtable(VFptr* table)
{
for (int i = 0; table[i] != nullptr; i++)
{
printf("[%d]:%p\n", i, table[i]);
VFptr f = table[i];
f();
}
cout << endl;
}
int main()
{
A aa;
B bb;
C cc;
//为了验证子类中的虚函数是存放在第一份虚表还是第二份虚表
//我们还是把虚表打印出来看看
//打印对象cc中继承A类型的虚表
PrintVFtable((VFptr*)(*((void**)&cc)));
B* p = &cc;
//打印对象cc中继承B类型的虚表
PrintVFtable((VFptr*)(*((void**)p)));
return 0;
}
打印结果如下:
所以我们可以得出结论:多继承派生类的未重写的虚函数放在第一个继承基类部分的虚函数表中。