前言 Q eZg l!
\J0fr'(S
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 E[8R
)xC@
2#hfBJg@
一、在union中存储对象 k=D}i\F8
[')C]YQb=
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? ,N`cH\
e*?@6E
#pragma warning(disable : 4786) )GC9%mF;
#include cFF'ygJ/
using namespace std; BV@xE
={]tklND
class TestUnion io1hUZ
{ AwQ7O z|(
public: }S_#*N)i
TestUnion(long l):data_(l) zY^QZceq"
{ X]T&kdQ6q
}; (- QvlpZ
int data_; 31> $;"
}; #vs=yR/tn{
dPmtU{E<M
typedef union _tagUtype_ LeTOVgjA|
{ )U5Ba^"fI
TestUnion obj; xb22:
}UT; EK=PY
OoqA`%
int main (void) u>y/<9]q8
{ 1> IA9]D7
return 0; j
:$Ruy
} 4!k0
.s8u?1b
&o]ic(74c?
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: &s>E~M0+J
?Tr\r1s]
class TestUnion }VDJ
{ 5xIOi(3`Q
public: 'Xb?vOU
int data_; ]r\d 5
}; Gj ka %
!0DOj["
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! MLk%U 4
lK yeG(
二、类中union的初始化 `vc?*"
sb"h:i>O4
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: kmZ
U;Z
vZJu=t
#pragma warning(disable : 4786) aP}30E*Y
#include 59X'-fg ,
Y0Bd[
using namespace std; RJ0:O
k,0lA#>
class TestUnion L_{gM`UFc
{ e]k\dj;,^%
enum StoreType{Long,Const_CharP}; ,E3Ze*(U
union 746['sf4c
{ tYST&5Kh~
const char* ch_; |Zm'! -_
long l_; JuM4Njz|
} data_; [+.P'6/[$R
StoreType stype_; }h=}!R'm
TestUnion(TestUnion&); >Nr~7s
TestUnion& operator=(const TestUnion&); 1P6!E*z\
public: 25wvB@0&
TestUnion(const char* ch); -?Kd[Ma
TestUnion(long l); K^f&+`v6_
operator const char*() const {return data_.ch_;} ]rMHO
operator long() const {return data_.l_;} S>nf]J`
}; :211T&B%A_
5JggU
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) <F6LC_
{ 0Ma3
} ~;D5j ) 9I
sB+
B,DF
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) Y'eE({)<K
{ s_RUb
} rOA{8)jIa*
Ds@nuQ
int main (void) C]GW u~QF
{ [\,Jy8t)\
TestUnion pszobj("yuankai"); V \Sl->:
TestUnion lobj(1234); a"bael
cout<(pszobj)< cout< #.W^7}H
return 0; ?f&O4H
} gv}J"anD
}J m~b9j
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: ipH'}~=ID
K!jMW
class TestUnion )7;E,m<:tO
{ gq~6jf>
enum StoreType{Long,Const_CharP}; 7I;A5f
union DataUnion //不能匿名 eccJt
{ ,f)#&}x*2+
DataUnion(const char*); //声明const char*构造函数 0jmPj
DataUnion(long); //声明long构造函数 (!"&c*
<
const char* ch_; IEeh9:Km
long l_; `Ti?hQm/
} data_;
y@2$sK3K
StoreType stype_; J[{?Y'RUM
TestUnion(TestUnion&); c#<p44>U
TestUnion& operator=(const TestUnion&); 07#e{
public: ds
"N*\.
TestUnion(const char* ch); 9D,/SZ-v
TestUnion(long l); rJw
Ws
operator const char*() const {return data_.ch_;} U])$#/ v
operator long() const {return data_.l_;} vHM,_I{
}; s~n@|m9k
^udl&>
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) \Jm^XXgS
{//注意data_(ch),这里直接引用data_ >}) W5Y+
} z 8y.@<6
y41,T&ja
TestUnion::TestUnion(long l):data_(l),stype_(Long) 5Zy%Nam'gN
{//注意data_(l),这里直接引用data_ W+`T:Mgh
} $c1xh.
=.\PG[
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) ?*dt JL
{ ck\TTNA
} `g^b Qx
-APbN(Vi
TestUnion::DataUnion::DataUnion(long l):l_(l) 0.z\YTZ9
{ MNu\=p\Eq
} s]'EIw}mo
{2T;^+KE
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!