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 名字,以及一组以花括号括住的成员声明。这段代码定义了名为 TokenValueunion,它可以保存一个 charintchar 指针或 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)的,否则就必须放在匿名名字空间中.

posted @ 2012-09-12 11:10  ForFreeDom  阅读(1465)  评论(0编辑  收藏  举报