编译器如何实现C ++继承?

时间:2013-07-12 14:21:26

标签: c++ class inheritance compiler-construction implementation

C ++支持继承。

但它是如何在编译器中实现的?

编译器是否将所有实现从父级复制并粘贴到子级?

2 个答案:

答案 0 :(得分:2)

就像成员变量一样,基类会导致子对象嵌入到派生类的所有实例中。基类的成员函数不会与派生类重复,而是在与基类对应的子对象上调用它们。

编译器知道这个子对象相对于完整对象的位置,并且在指针(或引用)与派生和基础之间存在强制转换(可能是隐式)的地方插入指针算法。这包括传递给基类型成员函数的隐藏this - 指针参数。

虚拟继承有点棘手,因为根据派生类型的不同,偏移量可能会有所不同。在这种情况下,编译器需要将偏移量作为变量存储在类实例中,以便可以在运行时查找(就像指向虚拟成员函数的指针一样,可能还有另一层间接涉及节省空间)。

答案 1 :(得分:2)

非常简化,如果我们谈论的是这样的话:

class A 
{
    public:
       int func1() { do something; }
       int func2() { do something; }
 };

class B : public A
{
    public:
       int func2() { do somethign else; }
};

B b;

b.func1();

那么编译器内部会发生什么(请记住,这是非常简化的,真正的编译器代码会更复杂,我敢肯定):

 ... fname = "func1" from the source code ... 
 ... object = "b"; 
function fn;
while (!(fn = find_func(object, fname)))  
   object = parent_object(object);
if (fn)
  produce_call(fn); 
else
  print_error_not_found(fname);

如果我们讨论的是虚函数,那么编译器将生成一个表,该表保存相应虚函数的地址,并根据类似的原则“查找存在的函数”为每个类生成表。这个班级或其父母之一。)

[在上面,我忽略了一个类可以拥有多个“父”类的事实 - 它不会改变事物的工作方式,只是代码必须维护一个列表或数组“更多”同级别的课程“]