含有类类型成员的union:
c++早期版本规定,在union中不能含有定义了构造函数或拷贝控制成员的类类型成员。
当union包含的是内置类型的成员时,编译器将按照成员的次序依次合成默认构造函数或拷贝控制成员。但是如果union含有类类型的成员,并且该类型自定义了默认构造函数或拷贝控制成员,则编译器将为union合成对应的版本并将其声明为删除的
所以需要使用类来管理union成员
class Token { public: //因为union 含有一个string成员,所以Token必须定义拷贝控制成员 Token():tok(INT), ival(0){} Token(const Token &t):tok(t.tok) { copyUnion(t);qDebug() << "....value constructer";} Token(Token&&t) noexcept:tok(t.tok) { copyUnion(t);qDebug() << "....move constrrcter";} Token &operator =(Token &&rhs) noexcept { if ( this != &rhs ) { if ( STR == tok && STR != rhs.tok ) { sval.~string(); } if ( STR == tok && STR == rhs.tok) { sval = rhs.sval; } else { copyUnion(rhs); } } qDebug() << ".....move operator="; return *this; } Token &operator=(const Token &rhs) { if ( this != &rhs ) { if ( STR == tok && STR != rhs.tok ) { sval.~string(); } if ( STR == tok && STR == rhs.tok) { sval = rhs.sval; } else { copyUnion(rhs); } } qDebug() << ".....value opeartor="; return *this; }
//如果union含有一个string成员,则我们必须销毁它,(调用析构函数会销毁对象,但是不会释放内存,如果需要的话,可以重新使用该空间) //因为析构函数不清楚union存储的值是什么类型,所以它无法确定应该销毁那个成员 ~Token() { if (STR == tok) sval.~string(); } //下面的赋值运算符负责设置union的不同成员 Token &operator =(const std::string &s) { if ( STR == tok ) { sval = s; } else { new (&sval) string(s); } tok = STR; return *this; } Token &operator =(char c) { if ( STR == tok ) { sval.~string(); } cval = c; tok = CHAR; return *this; } Token &operator =(int i) { if (STR == tok ) { sval.~string(); } ival = i; tok = INT; return *this; } Token &operator =(double d) { if ( STR == tok ) { sval.~string(); } dval = d; tok = DBL; return *this; } private: enum { INT, CHAR, DBL, STR } tok;//判别式 union {//匿名 union char cval; int ival; double dval; std::string sval; };//每个Token对象含有一个改未命名union类型的未命名成员 //检查判别式,然后酌情拷贝union成员 void copyUnion(const Token&rhs) { switch (rhs.tok) { case INT: ival = rhs.ival; break; case DBL: dval = rhs.dval; break; case CHAR: cval = rhs.cval; break; case STR: new (&sval) string(rhs.sval); break; default: break; } } };
union类(联合)硬性知识
union不能含有引用类型的成员,在c++新标准中, 含有构造函数或析构函数的类类型也可以作为union的成员类型。union可以为其成员指定public, protected和private保护标记,默认是共有的。union可以定义包含构造函数和析构函数在内的成员函数。但是不能继承也不能被继承,所以union不能含有虚函数。
匿名的union:
不能标记protected, private,也不能定义成员函数。