Eckel Vol1,pg283,不完整的类型规范,编译器在做什么
Eckel Vol1, pg283, Incomplete type specification, what is the compiler doing?
struct X;
struct Y {
void f(X*);
};
struct X { //definition
private:
int i;
public:
friend void Y::f(X*);
<SNIP'd>
};
"struct
Y
有一个成员函数f()
,它将修改类型为X
的对象。这有点难题,因为C++编译器要求您先声明所有内容,然后才能引用它,因此必须先声明结构Y
,然后才能声明其成员Y::f(X*)
在结构X
中声明为友元。但是要声明Y::f(X*)
结构X
必须先声明!这是解决方案。请注意,
Y::f(X*)
采用X
对象的地址。这是至关重要的,因为编译器始终知道如何传递地址,无论传递的对象如何,该地址都具有固定大小,即使它没有有关类型大小的完整信息。
所以这里有:
struct X; struct Y { ... }; struct X { ... };
我的问题是这样的:
为什么编译器坚持将
X
不完全声明为:struct X;
??毕竟,正如作者所指出的:"编译器总是知道如何传递地址这是固定大小的。这只是一个声明,告诉编译器
X
是一个结构体并且很快就会遵循,那么为什么编译器如此坚持要你输入字母:structX
;毕竟我本身没有使用X
??此时不会生成汇编语言代码。当它读取X*
时,它肯定可以说它是一个地址(指针)。为什么:需要struct X;
?声明函数的全部意义在于实际进行类型检查用法。因此,如果我这样做:
int foo(void); foo(30);
编译器会嚎叫。但是在上面,如果我不说:
struct X;
有什么区别?他只是检查我X
(函数名称)的拼写吗?为什么反转结构体 Y 和 X 的位置不起作用?这样:
struct Y; struct X { ... }; struct Y { ... };
我得到:错误:未使用不完整的类型
无效'struct main()::Y'
显然,编译器对我不完整的类型规范不满意
Y
(struct Y;
).但是缺少什么宝贵的信息??后所有结构Y
;应该告诉编译器Y
即将跟进(与我们在第一季度做了什么:struct X; struct Y {}; struct X{};
)为什么作者将结构
X
称为定义?如果我这样做:struct X { ... };
这肯定是一个宣言?当我实例化结构如下:X
福;那么这是一个定义?正确?我该怎么做:
struct X { friend void Y::f(X*); void f(Y*); }; struct Y { friend void X::f(Y*); void f(X*); };
为什么编译器坚持将 X 不完全声明为:结构体 X??毕竟,正如作者所指出的:"编译器总是知道如何传递一个固定大小的地址。
你没有:这也有效:
struct Y { void f(struct X*); };
class X {
int i;
friend void Y::f(X*);
};
你还有什么建议?
此外,在按值传递时,您甚至不必具有完整类型,除非您实际定义了方法:
struct Y { void f(struct X); };
// too early:
void Y::f(struct X) { /* whoops compile error */ }
class X {
int i;
friend void Y::f(X);
};
// ok here:
void Y::f(X) { /* compile success */ }
毕竟,正如作者所指出的:"编译器总是知道如何传递一个固定大小的地址。这只是一个声明,告诉编译器 X 是一个结构体并且很快就会遵循,那么为什么编译器如此坚持要你输入字母:
struct X;
毕竟我没有使用 X 本身??此时没有生成汇编语言代码。当它读取"X*"时,它肯定可以说它是一个地址(指针)。为什么是:需要struct X;
?
作者并没有告诉你所有令人讨厌的细节。编译器知道如何传递指针(地址),如果它知道X
是哪种对象。该语言允许某些指针(如指向可寻字机器上的char
的指针或指向函数的指针)具有不同的大小。
因此,您必须告诉编译器X
是内置类型的struct
,而不是函数或 typedef。
- 编译器对数组声明大小的计算。什么时候发生?
- 这个失败的测试是将零添加到空指针未定义的行为、编译器错误还是其他什么?
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 在使用包含冒号的类似函数的宏时,是什么导致了这种编译器差异?
- 我的设备上的 C++ 编译器版本是什么
- 处理编译器关于可能丢失数据的警告的最优雅方法是什么
- 让编译器告诉什么确切的纯虚拟方法使结构抽象?
- 这个编译器错误究竟希望我执行什么?
- Visual Studio 编译器的 record-gcc-switch 相当于什么?
- 如果字符串在 C/C++ 中没有 NUL 字符(以防编译器允许它通过)会发生什么情况?
- 编译器在这里做什么,允许在很少进行实际比较的情况下比较许多值
- 告诉编译器我希望变量始终存储在寄存器中的正确方法是什么
- openmpi 编译器有什么区别
- 使用不同的编译器 - 这有什么作用
- 编译器遇到返回语句时会做什么
- GCC,Apple LLVM和MSVC编译器的不同部分的名称是什么?
- GCC 编译器对类型转换有什么作用?为什么 mac 和 Linux 上的输出不同
- 编译器认为 int 是一个字符串.发生了什么事情
- 即使使用用户定义的构造函数,编译器什么时候仍会生成默认构造函数
- c++编译器什么时候开始考虑在字符串转义中使用两个以上的十六进制数字?