正常情况下,union 顺序应该是不重要的,但在语言设计缺陷被引发时,好像有点重要了。先看 C99 怎么解决问题的:
#include <stdio.h>
struct One {
int a;
};
struct Two {
int a;
int b;
};
struct Three {
int a;
int b;
int c;
};
struct Test {
int type;
union {
struct One u1;
struct Two u2;
struct Three u3;
};
};
int main()
{
// error C2078: too many initializers
//struct Test t = {2, 1, 2};
struct Test t = {.type = 2, .u2.a = 1, .u2.b = 2};
printf_s("%d, %d, %d\n", t.type, t.u2.a, t.u2.b);
return 0;
}
这段代码要在 VS2015 下编译,需要保存为 .c 文件,如果是默认用 .cpp 后缀,要改编译开关 Compile as C Code (/TC)。
问题在于,我们把短的结构体放在 union 最前面,导致编译器认定结构体初始化列表的元素的长度是由最短的那个结构体决定的。但我们用了 C99 的乱序初始化搞定了。然而,VS2015 的 C++ 不支持乱序初始化,以下是 C++ 版本。
#include <iostream>
struct One {
int a;
};
struct Two {
int a;
int b;
};
struct Three {
int a;
int b;
int c;
};
struct Test {
int type;
union {
One u1;
Two u2;
Three u3;
};
};
int main()
{
struct Test t = {1, 1};
// error C2078: too many initializers
//struct Test t = {2, 1, 2};
//struct Test t = {3, 1, 2, 3};
std::cout << t.type << ", " << t.u2.a << std::endl;
return 0;
}
把 union 顺序换一下,把 Three 放在最前,可以解决……如果您知道不改顺序的更好的方法,请不吝告知,仅限 VS2015,POD,不要用 class 构造函数的思路。