C++14中[class]/7中要点(7.5)的目的是什么

What is the purpose of bullet point (7.5) in [class]/7, in C++14?

本文关键字:是什么 class C++14      更新时间:2023-10-16

这基本上是我前面问题的延续。

这是C++14:中的[class]/7

标准布局类是指:

  • (7.1(-没有类型为非标准布局类(或此类类型的数组(或引用的非静态数据成员
  • (7.2(-不具有虚拟函数(10.3(和虚拟基类(10.1(
  • (7.3(-对所有非静态数据成员具有相同的访问控制(第11条(
  • (7.4(-没有非标准布局基类
  • (7.5(--在派生最多的类中没有非静态数据成员,并且最多有一个基类非静态数据成员,或者没有具有非静态数据会员的基类,以及
  • (7.6(--没有与第一个非静态数据成员类型相同的基类

考虑以下片段:

struct B{ int i; };
struct A : B{ int j; };

A满足要点(7.1(到(7.4(,但不满足(7.5(,因为A具有非静态数据成员,并且具有具有非静态的数据成员的基类。

A作为标准布局类有什么问题?

编辑

就我所能理解的这个问题的公认答案而言,如果我试图将指向A的指针投射到基类B的第一个数据成员并返回,那么上面的片段将具有未定义的行为,因为这句话是由OP:编写的

Within a class, members are allocated in increasing addresses according to the declaration order. However C++ doesn't dictate the order of allocation for data members across classes.

但这似乎并不能回答我的问题。例如,假设在某个编译器实现中,基本B将在内存中跟随struct A,而不是在它之前。但根据[conv.ptr]/3:,这与从指向派生类的指针到指向基类的指针的隐式转换相矛盾

类型为"pointer to cv D"的prvalue,其中D是类类型,可以是转换为"指向cv B的指针"类型的prvalue,其中B是基数D.的类别(第10条(

也就是说,如果存储器中的基本B跟在struct A之后,则上述隐式转换将无效。

标准为标准布局结构提供了两个重要保证:

  1. 第一个非静态数据成员(按声明顺序(或标准布局结构的偏移量为0([class.mem.general]/27(
  2. 可以定义两个这样的结构的公共初始序列,这是通过按声明顺序比较每个结构的成员而获得的;参见[class.mem.general]/23。当一个并集包含两个或多个成员,它们的类型是(可能不同的(标准布局结构时,只要你只读取公共的初始序列,它们之间就有有限形式的合法类型双关语;参见[class.mem.general]/26

这两种保证都依赖于这样一个事实,即在标准布局结构中,对于哪一个非静态数据成员是"非静态数据"没有歧义;第一";。第一个非静态数据成员位于偏移量0处,当将此标准布局结构与另一个标准布局结构进行比较时,将其与另一结构的第一个非静止数据成员进行比较,以确定它们是否属于公共初始序列。

如果标准放宽到允许示例中的类A成为标准布局,那么就必须解释哪个成员是第一个。如评论中所讨论的,实现可以自由地在j之前布置i或在i之前布置j。为了使A成为标准布局,该标准将不得不剥夺实现的自由。

只有在所有非静态数据成员首先在同一个类中声明的特殊情况下,才认为有必要要求所有实现对类进行布局,就好像所有非静态的数据成员都首先在最派生的类中声明一样,并且所有基类都不占用空间。

直接回答以下问题:

此项目符号的目的是允许非常简单的继承情况,其中只有一个类具有数据成员。

继承的数据布局是未指定的,因此标准可以完全禁止继承,但如果一个类没有数据,则标准会例外,以将结果仍视为标准布局。