前言 ~M%r.WFpA
k.>*!l0
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 u1O?`
.Ya]N+r*
一、在union中存储对象 1SeDrzLA
3}}~(
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? "|V{@)!t
,Khhu%$
#pragma warning(disable : 4786) 703=.xj
#include 7%L%dyN
using namespace std; @47MJzC
|&WeXVH E
class TestUnion ;|e {J$
{ D`PnY&ffT
public: Udv5Y
TestUnion(long l):data_(l) \2)a.2mAz
{ w<-8cvNhiz
}; [_Y\TdR
int data_; #bgW{&_y
}; 'F^nW_ryW
W+V#z8K
typedef union _tagUtype_ \ Xow#@[
{ pUki!TA
TestUnion obj; LGZ5py=xb
}UT; |3W\^4>,
ivsp):W
int main (void) 1ux~dP
{ |rkj$s,
return 0; S3]Cz$
} |\"vHt?@G
VQV7W
}C.M4{a\
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: V`?2g_4N
4Waot
class TestUnion
Fv=7~6~
{ )[Bwr
bn
public: N#'+p5|>
int data_; |xyr6gY
}; e|u|b
cMOvM0f
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! ~(kIr?^
FLdO
二、类中union的初始化 J;4x-R$W
uZ][#[u
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: GCCmUR9d
H S/1z
#pragma warning(disable : 4786) pisjfNT`o
#include jXq~ x"(
peqoLeJI
using namespace std; j|gv0SI_
w
6T{Zee
class TestUnion xxOo8+kA
{ #=/eu=
enum StoreType{Long,Const_CharP}; D7cOEL<
union Gs%IZo_
{ <y1V2Np
const char* ch_; un0tzz
long l_; rks+\e}^Z
} data_; -IhFPjQ
StoreType stype_; z52T"uW
TestUnion(TestUnion&); ?PORPv#
TestUnion& operator=(const TestUnion&); \ &1)k/
public: xExy?5H7
TestUnion(const char* ch); ^ a%U *>P
TestUnion(long l); ,\Gn
operator const char*() const {return data_.ch_;} :Z(?Ct&8
operator long() const {return data_.l_;} /=Bz[O
}; h+F@apUS
0-cqux2U
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) -e7|DXj
{ |gEA.}
pY
} I7b(fc-r
m)9N9Ii#)
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) 'Ht$LqG
{ ;hR!j!3}
} .CFaBwj
b $x<7l5C
int main (void) [^t"Hf
{ Frn#?n)S9
TestUnion pszobj("yuankai"); =BJ/ZM
TestUnion lobj(1234); T.="a2iS2
cout<(pszobj)< cout< h-h U=I8
return 0; lM Gz"cym
} eU_|.2
J'^s5hxn+0
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: 2{c ;ELq
k9UmTvX
class TestUnion g6EdCG.V
{ mtuq
enum StoreType{Long,Const_CharP}; 6u/3"A]'
union DataUnion //不能匿名 ^T"9ZBkb
{ r:K)Q@
DataUnion(const char*); //声明const char*构造函数 >1:s.[&
DataUnion(long); //声明long构造函数 zNRoFz.
const char* ch_; [YP8z~
long l_; #C|:]moe
} data_; _m;cX!+~_
StoreType stype_; =]oBBokV
TestUnion(TestUnion&); udB:ys
TestUnion& operator=(const TestUnion&); *{tn/ro6a
public: jo=XxA
TestUnion(const char* ch); =O1CxsKt6
TestUnion(long l); V S2p"0$3D
operator const char*() const {return data_.ch_;} \*6%o0c
operator long() const {return data_.l_;} mn\e(WoX
}; },0fPkVsU
N^q*lV#kob
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) <oV
_EZ
{//注意data_(ch),这里直接引用data_ m}6GVQ'Q
} ~ $#DB@b
:BCjt@K}
TestUnion::TestUnion(long l):data_(l),stype_(Long) R+lKQAyC0=
{//注意data_(l),这里直接引用data_ ?PiJ7|
} .{HU1/!
T2Cdw\
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) s`Z(f:/6*
{ `y0ZFh1>X
} /fA:Fnv
ItQI M#
TestUnion::DataUnion::DataUnion(long l):l_(l) ^C>i(j&
{ NWwfNb>
} Wf13Ab
=Xm
[
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!