C++编译器可以删除(虚拟)私有基类吗
C++ can (virtual) private base classes be removed by the compiler?
给定以下示例:
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定义的一部分,而不是编译器的私有规则(也就是说,一个平台上的所有编译器都必须使用相同的规则)。
相关文章:
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 子类地址等于虚拟基类地址?
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- 虚拟基类函数中派生类的大小
- 使(虚拟)函数在大多数派生类中无法访问中间基类中可访问,定义良好?
- 当键是虚拟继承中涉及的基类指针时,对 std::unordered_map 项的访问崩溃
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- 虚拟基类初始化
- googletest:测试基类具有纯虚拟方法的派生类时的核心转储
- 有没有办法在没有虚拟的情况下使用基类指针调用派生类函数
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- 虚拟基类在内部如何工作?编译器如何解析对基方法的调用?
- 无法使用在子类中定义的虚拟getter实现基类
- C++虚拟函数:基类函数是调用的,而不是派生的
- 关于C++从派生类调用在基类中实现的虚拟函数的问题
- 派生类调用非公共基类虚拟函数
- 使用基类虚拟方法
- 强制调用基类虚拟函数
- 强制调用长链下的基类虚拟函数
- 通过派生类虚拟方法调用基类虚拟方法