C++继承/ VTable问题

jam*_*o00 10 c++ virtual inheritance class vtable

更新:使用直接方法调用示例替换析构函数示例.

嗨,

如果我有以下代码:

class a
{
public:
    virtual void func0(); // a has a VTable now
    void func1();
};
class b : public a
{
public:
    void func0() { a::func0(); }
    void func2();
};
Run Code Online (Sandbox Code Playgroud)
  1. B中有VTable吗?B没有虚函数,但从b :: func0()调用:: func0()
  2. func1是否驻留在VTable中?这不是虚拟的.
  3. func2是否驻留在VTable中?
  4. 如果在b :: func0()中没有aa :: func0()调用,上述答案是否会有所不同?

谢谢

P S*_*ved 19

如果你声明虚函数,你也应该声明你的析构函数虚拟;-).

  1. B有一个虚拟表,因为它有一个虚函数,即func0().如果在基类中声明一个虚函数(包括析构函数),那么它的所有派生类都将具有相同签名虚函数的函数.它会使他们有一个vtable.而且,即使你没有func0明确地声明,B也会拥有vtable .

  2. 非虚函数不通过vtables引用.

  3. 见2.

  4. 不.Classes的vtable是基于类声明构造的.不考虑类的功能(更不用说其他功能).因此,B有一个vtable,因为它的功能func0()是虚拟的.

还有一个棘手的细节,虽然这不是你的问题的要点.您将函数声明B::func0()为内联函数.在gcc编译器中,如果虚拟函数是内联声明的,它会将其插槽保留在虚拟表中,该插槽指向为该内联函数发出的特殊函数(计为获取其地址,这使得内联发出).这意味着,函数是否内联不会影响vtable中的插槽数量及其对类的必要性.


Chr*_*isW 5

  1. 是的,因为它的基类有一个; 它的析构函数也是虚拟的(即使你没有将它声明为虚拟),因为基类的析构函数是虚拟的.

  2. 没有

  3. 没有.

  4. 实际上我认为当前代码不合法​​:即使你没有从~B显式调用~A,编译器也会在调用B析构函数后调用A析构函数.所以我认为即使编译器允许你也不应该从~B调用~A.