为什么结构的typedef名称不能与结构名称互换使用
Why can a typedef-name for a struct not be used interchangeably with the struct name?
以下代码(实际示例)不编译:
struct S {};
typedef struct S T;
S s = T(); // OK
struct T * p; // error: elaborated type refers to a typedef
T::T(){} // error: C++ requires a type specifier for all declarations
为什么语言设计不允许最后两行?
相关标准报价(N4140§7.1.3/8):
[注意:命名类类型或其cv限定版本的typedef-name也是类名(9.1)。如果使用typedef名称来标识详细类型说明符(7.1.6.3)、类定义(第9条)、构造函数声明(12.1)或析构函数声明(12.4)的主题,则程序格式错误。--尾注]
所以有三个不相关的问题。您提供的报价中的第一个:
struct T * p;
这是非法的,因为T
是typedef。
T{};
这在名称空间级别是非法的,但在其他概念中是合法的,例如作为全局初始化的一部分,或在函数内部:
T t = T{};
void f() { T{}; }
它实际上意味着创建一个值初始化类型为T
的临时对象。
T::T(){}
这将是默认构造函数的有效定义,除非您没有声明一个。如果您修改S
,使其具有用户声明的默认构造函数,则该构造函数将起作用:
struct S { S(); };
为什么语言设计不允许最后两行
在更新的问题中,这两行是:
struct T* p;
T::T() {}
第二个是合法的,但您试图定义一个尚未声明为成员的函数,因此这也与原始文本无关。这给我们留下了一个:struct T* p
。
动机来自C。用户定义的类型和其他名称的标识符似乎存在于不同的作用域中,当查找试图解析不符合struct
或enum
的名称时,它将忽略结构和枚举,当试图解析struct
或enum
时,它会忽略其他所有内容。以下是有效的C(和C++):
struct T {}; // 1
typedef struct S {} T; // 2
struct T t;
在C++中,查找规则发生了一些变化,您可以在不明确限定类型说明符的情况下使用类型说明符,但这是另一回事。此外,typedef-ed名称可以在其他上下文中使用,这在C.中是不可能的
一个特殊情况是查找详细的类型说明符,typedef-ed名称是否可以在详细的类型描述符中使用?如果是,上面程序的语义将发生变化,并且在C中,t
的类型为T
(在1中定义),在C++中,它将变为S
(在2中定义)。
请注意,这在某种程度上是一个疯狂的猜测,我没有制定规则,我不知道那里考虑了什么。注意,C和C++在这方面从来没有真正兼容过,类似的例子改变了C和C++中的语义:
int T;
void f() {
struct T { int data[10]; };
printf("%dn", sizeof(T));
}
该程序在C++中打印的数字将比在C中打印的大10倍。但是,使用一个类型而不必使用class
或struct
的能力可能比在少数情况下破坏兼容性更重要。。。
- 如何循环打印顶点结构
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 预处理器:插入结构名称中的前一个行号
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 孤立代码块在结构中引发异常
- 有什么方法可以遍历结构吗
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 无法将结构注册为增强几何体3D点
- 多成员Constexpr结构初始化
- C++将文本文件中的数据读取到结构数组中
- 如何重构类层次结构以避免菱形问题
- 如何在C++中序列化结构数据
- std::vector的包装器,使数组的结构看起来像结构的数组
- 没有为自己的结构调用列表推回方法
- 奇怪的结构&GCC&clang(void*返回类型)
- 在 c++ 中拥有一组结构的正确方法是什么?
- 可以在模板专业化中互换使用类和结构
- 为什么结构的typedef名称不能与结构名称互换使用