关于单继承中虚函数与虚表有关问题

关于单继承中虚函数与虚表问题?最近看到一句话:非虚拟继承时,无论派生类是否定义新的虚函数,基类和派生类

关于单继承中虚函数与虚表问题?
最近看到一句话:非虚拟继承时,无论派生类是否定义新的虚函数,基类和派生类总是共享一个虚函数表,不需要另加指向虚函数的指针。这里的共享是否指父类与子类只有一个虚表?
  我原来的理解是父类的虚表与虚指针,子类可以继承,如果子类中虚函数重写了,则在子类的虚表中虚函数会覆盖基类的虚函数地址,这样通过父类指针指向子类对象时,发生指针隐式转换,从而指向了子类中的虚函数,实现多态。
  大家帮我理一理虚函数与虚表吧,谢谢!!!

[解决办法]
指的可能是派生类不override基类实现,而顶多定义(即增加)新的虚函数这种情况。
如果派生类override了基类定义的虚函数,那基类和派生类的虚函数表不能共享的。

父类指针指向子类对象时,之所以能正确调用子类的虚函数实现,这个跟指针的隐式转换并没有直接关系,隐式转换都是编译时的事。这只跟父类和子类虚函数表中指针的指向不同有关。

不过这些都是编译器的实现细节,从语言的层面上,知道虚函数的行为基本就够了。
[解决办法]

探讨
最近看到一句话:非虚拟继承时,无论派生类是否定义新的虚函数,基类和派生类总是共享一个虚函数表,不需要另加指向虚函数的指针。这里的共享是否指父类与子类只有一个虚表?
我原来的理解是父类的虚表与虚指针,子类可以继承,如果子类中虚函数重写了,则在子类的虚表中虚函数会覆盖基类的虚函数地址,这样通过父类指针指向子类对象时,发生指针隐式转换,从而指向了子类中的虚函数,实现多态。
大家帮我理一理虚函……

[解决办法]
这句话是针对类对象的内存布局来说的,指的是派生类对象会使用基类子对象中的vptr,但是从两个类的角度来说,基类有基类自己的表,派生类也有派生类自己的表。


这个方式不是只有一个吗,派生类以插入的方式将数据成语及其方法插入父类的vtabl中,共享一个vptr
[解决办法]
1 不管是不是virtual继承,base class和derived class都有各自的vtable(不一定只有一个)。Derived class中vtable的virtual function来自三个地方:

1-1 继承自base class的virtual function(vf),没有经过该derived class的override
1-2 继承自base class的vf,被该derived class进行了override
1-3 该derived class扩充的vf

2 在单继承体系中

class层面上,每个class只有一个vtable。
object层面上,每个class object有一个vptr指向自己所属class的vtable。

3 在多继承体系中

class层面上,一个derived class拥有额外的(n-1)个vtable,对应所继承的n个base class(没错,是n个base class)。这有些复杂,比如

class A {}
class B {}
class C : public A, public B {}

class A有一个vtable——ta
class B有一个vtable——tb
class C将拥有两个vtable,C和A共享一个——tc1,B自己有一个——tc2。

object层面上,C object和A subobject的起始地址一致,A subobject的vptr所指向的vtable就是A和C共享的那个tc1。B subobject的起始地址独立,其vptr指向tc2。tc1因为是一个共享的vtable,它就是C的所有vf,它包括A的vf,可能经过了C的override,以及B的vf,可能经过了C改写。tc2是B的所有vf,但可能有些经过了C的override。

对这个体系vf的使用,牵扯到了潜在的compiler对this指针的调整以及thunk机制。

4 虚拟继承

将virtual base class的subobject放到了内存模型的共享区中,vbc有自己的viable。

非virtual base class在地址较小的固定区域。除了subobject拥有指向vbc的额外指针,和SI、MI的机制一致。