C++编译器可以删除(虚拟)私有基类吗

C++ can (virtual) private base classes be removed by the compiler?

本文关键字:基类 虚拟 编译器 删除 C++      更新时间:2023-10-16

给定以下示例:

class A
{
protected:
static void useful_function_without_side_effects() {...}
}
class B : private A
{
// B has no friends :(
public:
void travel_back_in_time() { super_useful_function(); }
}

问题1:编译器是否可以优化基类A,因为这个基类不会以任何方式真正影响B或它的运行时行为?

问题2:如果继承像这样被声明为私有虚拟,这种情况会改变吗?

class B : private virtual A

答案1:

非多态类在运行时完全没有代表。唯一可能存在的东西是对象和方法,它们被视为函数。该类只指示编译器访问对象的部分,并按照定义的方式解析方法调用。一旦直接解析,所有内容都将在运行时代码中进行硬编码。private限定符在这里没有任何更改。

如果你有问题的话,B派生的A类(没有字段)不会给B类的对象"增加大小"。如果一个类没有字段,但sizeof(A)将始终至少为1,那么这总是正确的。尽管也没有这样的规则,即B的大小必须是所有字段和基类的大小之和。

答案2

这增加了B类的大小。该标准并没有明确规定哪种方式。在典型的实现中,它总是将B类的大小扩展一个指针的大小,再加上a类的任何可能大小。

通常,虚拟继承是通过使用"指向自身的指针"来实现的。也就是说,派生类(A)的子对象在物理上是整个对象的一部分,但它从未被直接访问,而是通过整个对象中的指针访问。

当你有总大小为4:的无字段A和B时,这种情况就更少了

物理遗传:

B: [A: 0] [B extension: 4]

虚拟继承:

B: [A virtual: <pointer size>] [B extension: 4] [A shared subobject: 1]

这些事情的顺序可能因实现而异,尽管它是ABI定义的一部分,而不是编译器的私有规则(也就是说,一个平台上的所有编译器都必须使用相同的规则)。