一.虚函数表
虚函数表:存放着虚函数的指针数组
当创建一个对象,具有虚函数的会比不是虚函数的类对象要大,那是因为存放这虚函数表的指针,指向虚函数表,当我们创建派生类对象的时候,通过继承也会生成一张与基类值相同的虚函数表。
当在基类定义虚函数后,派生类通过继承的方式继承下来这张虚函数表,但是继承下来的虚函数表与父类的表并不相同,因为对虚函数表中重写的函数进行覆盖(重写)。
若派生类自己声明了虚函数,那么根据声明的顺序依次写在虚函数表中。
对于以下代码,并不会编译报错,并且会打印B::fun()
这是因为派生类的函数只实现功能,而由基类的函数作为借口
整体你可以当做两者结合
class A
{
public:
A ():m_iVal(0){test();}
virtual void func() { std::cout<<m_iVal<<‘ ’;}
void test(){func();}
public:
int m_iVal;
};
class B : public A
{
public:
B(){test();}
virtual void func()
{
++m_iVal;
std::cout<<m_iVal<<‘ ’;
}
};
int main(int argc ,char* argv[])
{
A*p = new B;
p->test();
return 0;
}
最终结果:0 1 2
相比对于以上的代码,大家可能一头雾水吧
new B时先调用父类A的构造函数,执行test()函数,在调用func()函数,由于此时还处于对象构造阶段,多态机制还没有生效,所以,此时执行的func函数为父类的func函数,打印0,构造完父类后执行子类构造函数,又调用test函数,然后又执行func(),由于父类已经构造完毕,虚表已经生成,func满足多态的条件,所以调用子类的func函数,对成员m_iVal加1,进行打印,所以打印1, 最终通过父类指针p->test(),也是执行子类的func,所以会增加m_iVal的值,最终打印2, 所以答案为C 0 1 2
对于多继承的时候
类有几个父类,如果父类有虚函数,则就会有几张虚表,自己的虚函数只会跟着第一张虚函数表的后面