首页 > 代码库 > C++ Primer 学习笔记_105_特殊工具与技术 --联合:节省空间的类
C++ Primer 学习笔记_105_特殊工具与技术 --联合:节省空间的类
特殊工具与技术
--联合:节省空间的类
联合是一种特殊的类。一个 union 对象可以有多个数据成员,但在任何时刻,只有一个成员可以有值。当将一个值赋给 union 对象的一个成员的时候,其他所有都变为未定义的。
为 union 对象分配的存储的量至少与包含其最大数据成员的一样多。联合提供了便利的办法表示一组相互排斥的值,这些值可以是不同类型的。
1.定义联合
作为例子,我们可能有一个处理不同各类数值或字符数据的过程。该过程可以定义一个 union 来保存这些值:
union ToKenValue { char cval; int ival; double dval; };
2.没有静态数据成员,引用成员或类数据成员
union可以指定保护标记使成员成为公用的,私有的或受保护的。 默认情况下, union 表现得像 struct:除非另外指定,否则 union 的成员都为 public 成员.
union 也可以定义成员函数,包括构造函数和析构函数。但是,union 不能作为基类使用,所以成员函数不能为虚函数。
union 不能具有静态数据成员或引用成员,而且,union 不能具有定义了构造函数、析构函数或赋值操作符的类类型的成员:
union illegal_memgers { Screen s; static int is; int &rfi; Screen *ps; };
3.使用联合类型
Union的名字是一个类型名:
ToKenValue first_token = {‘a‘}; ToKenValue last_token; ToKenValue *pt = new ToKenValue;
说明:可以用与显式初始化简单类对象一样的方法显式初始化 union 对象。但是,只能为第一个成员提供初始化式。该初始化式必须括在一对花括号中。first_token 的初始化给它的 cval 成员一个值。
4.使用联合的成员
可以使用普通成员访问操作符(. 和 ->)访问 union 类型对象的成员:
last_token.cval = ‘z‘; pt -> ival = 43;
给 union 对象的某个数据成员一个值使得其他数据成员变为未定义的。使用 union 对象时,我们必须总是知道 union 对象中当前存储的是什么类型的值。通过错误的数据成员检索保存在 union 对象中的值,可能会导致程序崩溃或者其他不正确的程序行为。
[实践]
避免通过错误成员访问 union 值的最佳办法是,定义一个单独的对象跟踪 union 中存储了什么值。这个附加对象称为 union 的判别式。
5.嵌套联合
Union最经常用做嵌套类型,其中判别式是外围类的一个成员:
class Token { public: enum TokenKind {INT,CHAR,DBL}; TokenKind tok; union { char cval; int ival; double dval; } val; };
[说明]枚举对象tok指出val成员中存储了那种值.
经常使用switch测试判别式,然后根据union中当前存储的值进行处理:
Token token; switch (token.tok) { case Token::INT: token.val.ival = 42; break; case Token::CHAR: token.val.cval = ‘a‘; break; case Token::DBL: token.val.dval = 3.14; break; }
6.匿名联合
不用于定义对象的未命名 union 称为匿名联合。匿名 union 的成员的名字出现在外围作用域中。
class Token { public: enum TokenKind {INT,CHAR,DBL}; TokenKind tok; union { char cval; int ival; double dval; }; };
因为匿名union不提供访问其成员的途径,所以将成员作为定义匿名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; }
匿名union不能有私有成员或受保护成员(要不然怎么访问^~^),也不能定义成员函数.