在学习Qt的QVariant时,Qt Create的说明手册中说道:
Because C++ forbids unions from including types that have non-default constructors or destructors, most interesting Qt classes cannot be used in unions.
大概意思是:因为c++禁止联合体中包含有非默认的构造函数和析构函数的类型,许多继承的Qt类不能在联合体中使用(这些类都有自定义的构造/析构函数)。
在c语言中并没有类的概念,所有类型都可以看做是基本数据类型的组合,因此在联合体(union)中包含结构体(struct)是一件习以为常的事情:
//c语言版本
#include <stdio.h>
typedef struct _stu {
int a;
char c;
}stu;
typedef union _uni {
stu s;
}uni;
int main(void)
{
uni u;
return 0;
}
编译通过。用c++改写上面例子,将结构体改成类:
//c++语言版本
#include <iostream>
class stu {
int a;
char c;
};
typedef union _uni {
stu s;
}uni;
int main(void)
{
uni u;
return 0;
}
编译通过。但是如果stu类自定义了构造函数:
class stu {
int a;
char c;
stu(){}
};
编译报错:
联合体是在需要将几种不同的类型的变量存放到同一段内存单元时使用的,即变量空间覆盖技术。上面例子中,假设编译通过,即c++标准允许联合体中有自定义的构造函数,那在进行联合体空间分配时要不要执行这个构造函数?
(1) 假设要,而联合体中有多个自定义了构造函数的类存在,每个构造函数的实现体是对该联合体的占据的空间执行相关初始化操作,那么联合体占据的空间和程序员设计的初衷不一样了:程序员使用到联合体中的某个类对象时,它是一个没有等价于没有被初始化,或者瞎初始化的对象。另外,如果其中一个类的自定义构造函数做了动态内存分配,而该类不是程序员访问联合体的访问方式,那么该动态分配的内存空间将会造成内存泄漏。
(2) 假设不要,而联合体中的类包含了虚函数,那么该类的虚函数表将不会得到初始化,虚函数无意义。
综上,c++标准决定,c++联合体中不允许定义有自定义构造函数的类,同理,不允许定义自定义了拷贝构造函数、析构函数的类。那为什么用默认的构造/析构/拷贝构造函数就可以?因为c++标准知道默认的构造/析构函数的操作的实现体什么都不做,拷贝构造函数只是实现浅拷贝。