当S是T的一个普通子类时,使用S数组是否可以安全使用T的数组?

Rob*_*edy 11 c++ arrays inheritance

考虑一对相关结构的以下声明.后代类不添加任何成员变量,唯一的成员函数是一个构造函数,它不会做任何事情,只是将其所有参数转发给基类的构造函数.

struct Base {
  Base(int a, char const* b):
    a(a), b(b)
  { }
  int a;
  char const* b;
};

struct Descendant: Base {
  Descendant(int a, char const* b):
    Base(a, b)
  { }
};
Run Code Online (Sandbox Code Playgroud)

现在考虑使用这些类型的以下代码.函数foo期望接收一个数组Base.但是,main定义一个数组Descendant并将其传递给它foo.

void foo(Base* array, unsigned len)
{
  /* <access contents of array> */
}

int main()
{
  Descendant main_array[] = {
    Descendant(0, "zero"),
    Descendant(1, "one")
  };
  foo(main_array, 2);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

是否定义了该程序的行为?答案是否取决于它的主体foo,例如它是写入数组还是只读取它?

如果sizeof(Derived)不相等sizeof(Base),则根据前一个关于指向派生对象数组的基指针的问题的答案,未定义行为.但是,这个问题中的对象是否有可能具有不同的大小?

Jos*_*hua 0

谨防!虽然这在您的编译器中几乎肯定是正确的,但标准并不能保证这可以工作。

至少添加 if (sizeof(Derived) != sizeof(Base)) logAndAbort("Derived 和 Base 之间的大小不匹配"); 查看。

如果您想知道,对此安全的编译器是一对一的,其中大小不会改变。标准中留下了一些东西,允许派生类与基类不连续。在发生这种情况的所有情况下,大小都必须增长(出于显而易见的原因)。

  • 对于静态断言?我无法想象为什么。它们在编译时进行评估。运行时断言是可以被禁用的。 (3认同)