前言 zi-+@9T
X! 2|_
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 ~ml\|
q!ZmF1sU
一、在union中存储对象 e0$mu?wd-
bR8)s{p6
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? SD.ze(P
OT *W]f
#pragma warning(disable : 4786) .ERO*Tj
#include 2~`dV_
using namespace std; ,o}[q92@w
Y4714
class TestUnion &9ZIf#R
{ H~G=0_S
public: ^@19cU?q
TestUnion(long l):data_(l) =OHDp7GXO>
{ d.}rn"(z
}; 8U(a&G6gn
int data_; F
Qk;
}; AQV3ZVP
ncA2en?
typedef union _tagUtype_ y]CJOC)/K
{ M^[jA](a
TestUnion obj; qt:->yiq+
}UT; Wey\GQ`"8
'PYl%2
int main (void) 3)-#yOr
{ +nZG!nP
return 0; #-f^;=7
} 5-3gsy/Mo
^7''x,I
.XE]vo
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: ?#[K&$}
l2v}PALs
class TestUnion 3AL.UBj&}
{ ueg X
public: }I10hy~W
int data_; 5 O6MI4:
}; :Aa^afjJw
8&;dR
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! DVS7N_cx2o
ri^yal<'
二、类中union的初始化 n$?oZ*;
}rQ*!2Y?
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: G`P+J
;8v5 qz
#pragma warning(disable : 4786) ( 0h]<7
#include i~9)Hz;!
Cn<kl^!Q-
using namespace std; |S8pq4eKJ_
C,]Ec2
class TestUnion 8(I"C$D!k
{ z? aDOh
enum StoreType{Long,Const_CharP}; @gj5'
union NAU<?q<)
{ Xo5L:(?K
const char* ch_; i,HAXPi
long l_; aF=VJ+5
} data_; o MAK[$k;
StoreType stype_; =ht@7z8QM
TestUnion(TestUnion&); EAkP[au.
TestUnion& operator=(const TestUnion&); #n7{ 3)
public: \[&]kPcDl
TestUnion(const char* ch); ')aYkO{%sb
TestUnion(long l); X<{m;T `
operator const char*() const {return data_.ch_;} &Xav$6+Z1J
operator long() const {return data_.l_;} Ll`apKr
}; s^
a`=kO
5eLPn
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) 5 9vGLN!L
{ ;@
e|}Gk
} @e7+d@O<
3IkG*enI
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) r__M1
!3
{ %Fv)$ :b
} #? *jdN:
)'g vaT
int main (void) ^n]s}t}csV
{ lrzW H0Q
TestUnion pszobj("yuankai"); 3{l"E(qqZ
TestUnion lobj(1234); 0{yx*}.
cout<(pszobj)< cout< $3ILVT
return 0; ^:j$p,0e*S
} GM/1ufZH
iiTUhO )
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: e'Pa@]VaC
Cw}\t!*!
class TestUnion \);rOqh
{ X@)lPr$a
enum StoreType{Long,Const_CharP}; 2$91+N*w9
union DataUnion //不能匿名 1rEP)66N
{ Xwi&uyvU&
DataUnion(const char*); //声明const char*构造函数 TG9)x|!
DataUnion(long); //声明long构造函数 UPYM~c+}
const char* ch_; bqO"k t
long l_; 1#(1Bs6X
} data_; "J#:PfJ%
StoreType stype_; -ZB"Yg$l
TestUnion(TestUnion&); Exr7vL
TestUnion& operator=(const TestUnion&); 7'S]
public: 63HkN4D4
TestUnion(const char* ch); {E/TC%
TestUnion(long l); kXr%73s
operator const char*() const {return data_.ch_;} GpL#,q Yc
operator long() const {return data_.l_;} E@FenCF
}; m
C Ge*V}
0 *\=Q$Yy
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) @2gMtf?<
{//注意data_(ch),这里直接引用data_ U6Ak"
} ThxrhQ
q[+
&; \v_5N6
TestUnion::TestUnion(long l):data_(l),stype_(Long) v,&2!Zv
{//注意data_(l),这里直接引用data_ sFQ|lU" n
} 3_$eQ`AAA
Q6K)EwN
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) U\ued=H
{ F
4/Uu"J:
} R=PzR;8
^ne8~
;Q
TestUnion::DataUnion::DataUnion(long l):l_(l) 7,TWCVap
{ ~|rkt`8p
} 5WT\0]RUa
' T]oV~H
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!