含有类类型成员的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,也不能定义成员函数。