C++中,虚基类是如何避免两义性的?
C++的继承中的基类就是派生类的一个子对象,也就是说基类是派生类的一个子部分,它占用派生类的一部分内存。
当B类从A类派生时,B类对象中就会有sizeof (A)大小的存储空间用于存储A类子对象。当通过B类对象来访问A类的成员时,产生的访问指令使用的地址是B对象的起始地址 + A对象在B对象的偏移量 + A成员对A对象起始地址的偏移量。,通过这种方式就可以通过派生类来访问基类成员,这个过程其实很像将基类对象作为派生类的成员对象。如果B对象中有多个A类子对象那么偏移量使用那一个呢? 编译器在这里不能做任何决定,所以就出现二义性错误。上面所说的计算完全由编译器完成。
当通过派生类来访问基类成员时,相应的访问指令中的地址都将被转换为派生类中基类对象的地址。对于单继承派生类中的基类对象只有一个所以地址转换没有问题。对于有共同基类的继承,派生类的内存中就会有那个共同基类的多个副本,所以地址转换就会出现问题。通过虚基类,那个共同基类在最终派生类中只有一个副本,地址转换就像单继承一样。这里的实现估计是需要额外的指针以指定虚基类子对象的位置。所以虚基类是有性能开销的。
基类的成员函数在派生类中不占存储,成员函数只有一个副本。
实际上对于普通继承来说,组合和继承是差不多的。所以有人就建议优先使用组合。
如果只有爷类有这个函数。派生类父类母类没有,孙类也没有。
那么调用孙类对象调用爷类函数时会有两义性。如果寻址方式是孙类起始地址跳到爷类起始地址,那么就不存在两义性。
也就是说,寻址是一层一层上去的?就是说,孙类先到上一层,上一层再到爷类。因为去上一层有多条路径,所以两义性报错?
回答发到你的私信上了,看看吧
我想问唯一一份,是怎样产生的?比如爷类hello()函数,派生父类,母类。 然后又共同派生子类。
那么创建子类对象。平常来说,子类对象中,父类作用域中有hello() 母类作用域中有hello()
但虚基类只产生一个hello() . 那是怎么回事?是把父母作用域中的hell()没了?把hello()添加到子类本身的作用域中?
没有将父母的弄没有,而是所有的都只有一个,如果是数据成员,则每个派生类都只有唯一的一个
如果是函数,派生类如果没有重写,则都指向这个最终虚基类的了