为何嵌套结构体含外部结构体成员时,在成员函数内声明可编译?
类与函数作用域中嵌套结构体的类型完整度问题
我有一段可编译的代码,但将其中的IncResult结构体从成员函数inc()内部移到Num结构体的作用域中时,编译会失败。我理解编译器有时无法处理不完整类型,但疑惑为何将结构体移到函数内部就能解决问题,我认为无论IncResult放置在何处,编译器对外部类Num的信息掌握没有差异。
代码如下:
#include <fmt/printf.h> struct Num { // IncResult moved here does not work: // error: field has incomplete type 'Num' auto inc() { struct IncResult { bool _event; Num result; }; return IncResult{(val+1)%2==0,Num{val+1}}; } int val = 0; }; int main() { Num num{10}; auto [eleven_even, eleven] = num.inc(); fmt::print("{}, {}\n", eleven_even ? "even " : "odd ", eleven.val); auto [twelve_even, twelve] = eleven.inc(); fmt::print("{}, {}\n", twelve_even ? "even " : "odd ", twelve.val); }
问题原因解析
核心差异在于编译器处理类定义和函数体的时机不同:
把
IncResult放在Num类作用域时:
编译器从上到下逐行处理类定义,当遇到IncResult里的Num result;时,Num类还没定义完成(后面还有int val = 0;未处理),此时Num属于不完整类型。而C++要求结构体的成员必须是完整类型(因为要确定整个结构体的大小和内存布局),因此编译器会抛出"field has incomplete type 'Num'"的错误。把
IncResult放在inc()函数内部时:
即使成员函数的定义写在类内部,函数体的实际解析会延后到整个Num类定义完成之后。此时Num已经是完整类型,IncResult里声明Num result;完全符合类型要求,编译自然可以通过。
简单总结:类作用域内的嵌套结构体是在类的定义过程中被解析的,此时外部类还不完整;而函数内部的嵌套结构体是在类完全定义后才被解析,外部类的类型信息已经完整。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

