C ++中成员函数的内存实现

时间:2010-07-04 13:37:33

标签: c++ inheritance

我在Wikipedia读了一篇关于虚拟桌子的文章。

class B1
{
public:
  void f0() {}
  virtual void f1() {}
  int int_in_b1;
};

class B2
{
public:
  virtual void f2() {}
  int int_in_b2;
};

used to derive the following class:

class D : public B1, public B2
{
public:
  void d() {}
  void f2() {}  // override B2::f2()
  int int_in_d;
};

阅读之后,我不禁想知道如何在C ++中实现非虚拟成员函数。是否有一个单独的表,如v-table,其中存储了所有函数地址?如果是,那么这个表被调用了什么以及继承期间会发生什么?

如果没有,那么编译器如何理解这些陈述?

D * d1 = new D;
d1->f0();    // statement 1

编译器如何解释f0()是B1的函数,并且由于D公开继承了D,它可以访问f0()。根据文章,编译器将语句1更改为

(*B1::f0)(d)

3 个答案:

答案 0 :(得分:7)

非虚拟成员函数的实现类似于接受隐藏this参数的全局函数。编译器在编译时知道基于继承树调用哪个方法,因此不需要运行时表。

答案 1 :(得分:1)

this之外,我只能说普通成员函数只是一个类中的内存地址(我甚至认为该类的每个对象在内存中使用相同的“函数指针”,但是自己的变量)。 v表是运行时重定向的一种形式,因为编译器无法知道它正在处理的究竟的对象(显然是由于多态性)。

答案 2 :(得分:1)

  

是否有一个单独的表,如v-table,其中存储了所有函数地址?

它们存储在调用它们的位置。

举个例子:只要 f0 方法是非虚拟的,编译器就知道它的地址是什么,因为只有一种可能性。设地址为0xABCD。然后代码

d1->f0();    // statement 1

编译为说明:

// push onto the stack 'this' pointer, as you pointed out the address must
// be earlier translated from D class to B1 which is not presented here
push d1

call 0xABCD // call method at known address (jump to this address)