C++:多重继承中类对象的意外大小

标签 c++ inheritance sizeof

我注意到多重继承中的奇怪行为。让我们看下面的例子:

#include <iostream>
using namespace std;

struct A {};
struct B : public A { double x; };
struct C : public A, public B {};

int main() {
    cout << "Size of double: " << sizeof(double) << endl;
    cout << sizeof(A) << ", " << sizeof(B) << ", " << sizeof(C) << endl; // gives 1, 8, 16
}

A 类型的大小为 1(奇怪,但可以接受),B 类型的大小等于 8(与 double 类型相同,这是预期的),但 C 类型的大小...等于 16。这是更奇怪的是,当我试图找到意想不到的变量时,我无法识别它。

struct D { double a, b; };

C c;
auto &d = reinterpret_cast<D&> (c);
d.a = 1;
d.b = 2;

cout << c.x << endl; //gives 2
cout << c.B::x << endl; //gives 2
cout << c.C::x << endl; //gives... 2

cout << d.a << ", " << d.b << endl; //gives 1, 2

我通过这种方式获得了一个对象中完全出乎意料的数据字段,我无法以正常方式访问它。有什么办法可以解释吗?这是 C++ 编译器的预期行为吗?

顺便说一句,代码是在 Visual Studio 2015 64x 中编写和编译的,但是当我在 g++ (Ubuntu) 上编译第一部分时,结果是相同的 - 1、8、16。

啊,具体说明我的问题——我想存储大量指定为继承类型的数据,这就是为什么我担心无用的保留字节。如果有人有解决方案,我会很高兴听到 - 即使它是一些 #define 或编译选项。

最佳答案

这里真的没有太多惊喜:

  1. C 中有两个 A 子对象:第一个直接由 C 继承,第二个由 B 间接继承。这两个子对象需要有不同的地址。
  2. B 中的 double 想要与合适的地址对齐,即,如果需要,将进行填充以确保它位于 8 字节边界(通常; 没有强制要求填充或任何此类填充的大小)。
  3. 要创建一个对象数组(定义 sizeof() 报告的大小),将根据直接 A 子对象所在的大小来填充对象。

请注意,问题的存在完全是因为您有两个相同类型的空碱基!如果您有另一个也为空的基数,它可以合法地共享 A 的地址,并且整个对象大小将仅为 8

关于C++:多重继承中类对象的意外大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41396752/

相关文章:

c - VS 2010 中的枚举大小选项

c++ - 关于 C++ 中 sizeof 运算符的强大功能

c++ - 如何使 std::regex 在字符串中的特定位置开始匹配?

c++ - 什么 C++ 编译器同时适用于 Linux 和 Windows?

c++ - 分解字符串并使用 keybd 发送字符

卡程序中的 Java getter 和 setter 问题

java - 如何创建子类,使其属性值不会被父类覆盖?

c++ - 尝试在 dev C++ win7 中编译 winsock 程序 - 错误

c++ - 创建继承对象的方法

c - C 中不一致的 sizeof 行为