2009-09-05 84 views
10

更新:用直线方法调用示例替换了析构函数示例。C++继承/ 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(); 
}; 
  1. 是否有虚函数表B中? B没有虚函数,但从b :: func0()调用:: func0()
  2. func1驻留在VTable中吗?这不是虚拟的。
  3. func2是否驻留在VTable中?
  4. 如果b :: func0()中没有a :: func0()调用,上面的答案会不同吗?

感谢

+5

如果你在这样的问题中告诉你正在使用什么编译器,我会很高兴。虚拟表格是特定于实现的,尽管要努力将其格式标准化。 – 2009-09-05 16:08:53

+2

'b :: func0' **是**虚拟 – 2009-09-05 18:02:38

回答

19

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

  1. B具有一个虚拟表,因为它有一个虚拟的功能,即func0()。如果您在基类中声明一个函数(包括析构函数)为虚拟的,则其所有派生类都将具有相同签名虚拟函数。这将导致他们有一个虚拟表。而且,即使您没有明确声明func0,B也会拥有该vtable。

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

  3. 请参阅第2

  4. 号类虚函数表是基于类声明构成。不考虑班级功能的身体(更不用说其他功能)。因此,B有一个vtable,因为它的功能func0()是虚拟的。

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

+0

已更新。另外,基本上,如果函数在继承层次结构中的任何*基类中声明为虚拟,那么即使直接基类(1级以上)不会将其标记为虚拟,该函数也是虚拟的? – jameszhao00 2009-09-05 16:49:08

+0

显着的答案。应该是被接受的。从我+1。 – 2009-09-05 18:17:18

+0

@ jameszhao00:也更新了答案。你知道它是正确的:如果任何间接基类(即当前类的某个父类的某个父类的父类)声明了虚函数,那么它在当前类中也是虚拟的。请注意,重载函数(void f(int)与void f(double)相比)被视为不同的函数。 – 2009-09-10 12:49:59

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

  2. 没有

  3. 号其实我并不认为当前的代码是合法的:编译器将调用析构函数,如果你不”它调用在B的析构函数即使t明确地从〜B调用〜A;所以我认为即使编译器允许你也不应该从〜B调用〜A。

+0

对不起。我不应该使用析构函数作为例子。更新。 – jameszhao00 2009-09-05 16:41:54

3

参照更新的例子:

  1. 是,b具有虚表。注意b :: func0()是虚拟的(重写a :: func0()),即使你没有明确地将它标记为虚拟的。奇怪的C++“漏洞”,我猜。
  2. 编号非虚函数不驻留在vtable中。
  3. 请参阅2.
  4. 否。您已覆盖a:func0();无论你是否调用:: func0()都没关系。

一些额外的注意事项(编译器相关的,但这些都是很常见的概括):

  • b每个实例都将有一个指向虚函数表,因为你从一个类派生具有虚拟功能。
  • 即使您没有定义b :: func0(),情况也会如此
  • 在这种情况下,编译器可能有b点的情况下,以一个的静态虚表,或者它可能为b创建一个静态虚函数表,并用指针填充它指向的一个成员。
  • 但它仍然需要,这样就可以适当地通过指针一个访问b一个实例。
1
  • 如果基类的功能是虚拟的,然后如果你重写派生类的功能它是含蓄虚拟,即使你没有明确指定。如果类具有虚函数,那么它有一个v表。
  • 存在的虚函数表只有虚函数,功能1不会驻留在虚函数表
  • 函数2不会驻留在虚函数表一样的道理以上
  • 创建虚表的不依赖于你是否调用从基类,函数或从别的地方。函数调用不决定创建vtable。