C++学习笔记二十四-Union
概述:
1.联合是一种特殊的类。一个 union 对象可以有多个数据成员,但在任何时刻,只有一个成员可以有值。当将一个值赋给 union 对象的一个成员的时候,其他所有都变为未定义的。
2.为 union 对象分配的存储的量至少与包含其最大数据成员的一样多。像任何类一样,一个 union 定义了一个新的类型。
3.像任何类一样,union 类型定义了与 union 类型的对象相关联的内存是多少。每个 union 对象的大小在编译时固定的:它至少与 union 的最大数据成员一样大。
一、定义联合:
联合提供了便利的办法表示一组相互排斥的值,这些值可以是不同类型的。作为例子,我们可能有一个处理不同各类数值或字符数据的过程。该过程可以定义一个 union 来保存这些值:
// objects of type TokenValue have a single member, // which could be of any of the listed types union TokenValue { char cval; int ival; double dval; }; 一个 union 定义以关键字 union 开始,后接(可选的)union 名字,以及一组以花括号括住的成员声明。这段代码定义了名为 TokenValue 的 union,它可以保存一个 char、int、char 指针或 double 值。
二、联合自身的特点:
1.某些(但不是全部)类特征同样适用于 union。例如,像任何类一样,union 可以指定保护标记使成员成为公用的、私有的或受保护的。默认情况下,union 表现得像 struct:除非另外指定,否则 union 的成员都为 public 成员。
2.union 也可以定义成员函数,包括构造函数和析构函数。但是,union 不能作为基类使用,所以成员函数不能为虚数。
3.union 不能具有静态数据成员或引用成员,而且,union 不能具有定义了构造函数、析构函数或赋值操作符的类类型的成员,
这个限制包括了具有带构造函数、析构函数或赋值操作符的成员的类。
三、使用联合类型:
union 的名字是一个类型名:
TokenValue first_token = {'a'}; // initialized TokenValue
TokenValue last_token; // uninitialized TokenValue object
TokenValue *pt = new TokenValue; // pointer to a TokenValue object
像其他内置类型一样,默认情况下 union 对象是未初始化的。可以用与显式初始化,简单类对象一样的方法显式初始化 union 对象。但是,只能为第一个成员提供初始化式。该初始化式必须括在一对花括号中。first_token 的初始化给它的 cval 成员一个值。
四、使用联合的成员:
可以使用普通成员访问操作符(. 和 ->)访问 union 类型对象的成员:
last_token.cval = 'z'; pt->ival = 42;
给 union 对象的某个数据成员一个值使得其他数据成员变为未定义的。使用 union 对象时,我们必须总是知道 union 对象中当前存储的是什么类型的值。通过错误的数据成员检索保存在 union 对象中的值,可能会导致程序崩溃或者其他不正确的程序行为。
五、匿名联合:
1.不用于定义对象的未命名 union 称为匿名联合。匿名 union 的成员的名字出现在外围作用域中。例如,使用匿名 union 重写的 Token 类如下:
class Token {
public:
// indicates which kind of token value is in val
enum TokenKind {INT, CHAR, DBL};
TokenKind tok;
union { // anonymous union
char cval;
int ival;
double dval;
};
};
2.因为匿名 union 不提供访问其成员的途径,所以将成员作为定义匿名 union 的作用域的一部分直接访问。重写前面的 switch 以便使用类的匿名 union 版本,如下:
Token token;
switch (token.tok) {
case Token::INT:
token.ival = 42; break;
case Token::CHAR:
token.cval = 'a'; break;
case Token::DBL:
token.dval = 3.14; break;
}
3.匿名 union 不能有私有成员或受保护成员,也不能定义成员函数。
4.匿名union还具有以下约束:
1).因为匿名联合不使用点运算符,所以包含在匿名联合内的元素必须是数据,不允许有成员函数,也不能包含私有或受保护的成员;
2).全局匿名联合必须是静态(static)的,否则就必须放在匿名名字空间中.