前言 u[/m|z
/&{$ pM|?
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 [$"n^5_~
:2-pjkhiwY
一、在union中存储对象 R&';Oro
/BV03B
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? 5
Ho^N1q
Fa_VKAq
#pragma warning(disable : 4786) ]Ww?QhJ
#include ?6jkI2w
using namespace std; X>.
NFB
e|D;OM
class TestUnion X'% ;B
{
\qR %%S
public: pBP.x#|
TestUnion(long l):data_(l) ku
a)
K!
{ S^<g_ q
}; }~h(w^t
int data_; XNb ZNaAd
}; TkO[rAC
Mz;[ +p
typedef union _tagUtype_ Gkxj?)`
{
ld7v3:M
TestUnion obj; >ap1"n9k
}UT; `VL}.h
zf>5,k'x'A
int main (void) m&iH2|
{ ^T,Gu-2>
return 0; la?Wnw
} _ _>.,gL7
i^!ez5z
D^;*U[F?
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: TSsKfexQ
D'hW|
class TestUnion @M8|(N%
{ k') E/n
public: FsGlJ
int data_; !!nuAQ"E[
}; fn/7wO$!
`H3.,]
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! c$QX)V
;u(Du-Os!
二、类中union的初始化 b]JI@=s?
on7I
l
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: 5I@w~z
^v@4|E$
#pragma warning(disable : 4786) }V|{lvt.
#include ]k8/#@19
G^1b>K
using namespace std; pBC<u
<p?&udqD
class TestUnion 8g>b
{ ,[nm_^R*\
enum StoreType{Long,Const_CharP}; Jj^GWZRu
union Sm2>'C
{ fXQiNm[P
const char* ch_; V=:_ d,
long l_; "XLe3n
} data_; da$BUAqU
StoreType stype_; jAsO8
TestUnion(TestUnion&); 3v!~ cC~cI
TestUnion& operator=(const TestUnion&); ehAu^^Q>
public: cxYfZ4++m
TestUnion(const char* ch); @)8]e
S7
TestUnion(long l); oT|m1aGE
operator const char*() const {return data_.ch_;} `4CWE_k
operator long() const {return data_.l_;} 7>
Pgc
}; /MOnNnV
Cv=GZGn-
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) g9my=gY
{ 7XyOB+aQO
} BvSIM%>h
\`xkp[C
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) y^FOsr
{ 9|S` ub'
} :a<hQ|p
g3?U#7i
int main (void) |[cdri^?D
{ {sC=J hs-
TestUnion pszobj("yuankai"); j:1uP^.
TestUnion lobj(1234); f8:$G.}i
cout<(pszobj)< cout< p`+VrcCBOd
return 0; /4joC9\AB
} I*1S/o_xI
Eo{EKI1
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: o+g4p:Mf
wy4q[$.4v
class TestUnion &(&
{ '0+$ m=
enum StoreType{Long,Const_CharP}; \-.
Tg!Q6
union DataUnion //不能匿名 J^I7BsZ
{ amB@N6*
DataUnion(const char*); //声明const char*构造函数 \}inT_{g
DataUnion(long); //声明long构造函数 Y~"9L|`f/
const char* ch_; :J(sXKr[C
long l_; @PcCiGZ
} data_; \/Ij7nD`l%
StoreType stype_; MMD<I6Iyv
TestUnion(TestUnion&); zd`=Ih2Wx
TestUnion& operator=(const TestUnion&); -WT3)On
public: e!o(g&wBj
TestUnion(const char* ch); cj(X2L
TestUnion(long l); hswTn`f
operator const char*() const {return data_.ch_;} f:%SW
operator long() const {return data_.l_;} mpef]9
}; T#iU+)-\%
&
QY#3yj=
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) ]R Mb,hJ
{//注意data_(ch),这里直接引用data_ qiNliJ>40E
} "oE* 9J?e
K~>jApZ%
TestUnion::TestUnion(long l):data_(l),stype_(Long) "r-l8r,
{//注意data_(l),这里直接引用data_ vO$ra5Z
} *:arva5
Sa}D.SBg
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) bc}dYK3$q
{ ]M4NpUM
} v>WB FvyD
:k1$g+(lP
TestUnion::DataUnion::DataUnion(long l):l_(l) Z! YpklZ?~
{ iUNnPJh
} 5a$$95oL
#O</\|aH)i
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!