前言 K;K0D@>]HR
MBLZ:A |
C
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 D:P(;
z4u.bU
一、在union中存储对象 {q>%Sr]9
EOPx4+o
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? osV6=
w OL,L U
#pragma warning(disable : 4786) Z0gtliJ@
#include \aSP7DzqQ
using namespace std; )g5?5f;
LI,wSTVjC
class TestUnion g_>&R58
{ :e<jD_.X
public: ?Uql30A
TestUnion(long l):data_(l) Hv6h7-
{ jIh1)*]054
}; &/@V$'G=
int data_; ZmK=8iN9J
}; l9K`+c+t
RpdUR*K9x
typedef union _tagUtype_ ^[<BMk
{ v,4{:y]p
TestUnion obj; Ni~IY#
'
}UT; M/ S~"iD
==Gc%
int main (void) Gp%po@A&
{ Yf0 KG
return 0; 3Z*r#d$nh:
} <2U#U;
;m7V]h? R
ZTmy} @l
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: ljFq ;!I5
%=**cvVy
class TestUnion b.*LmSX#
{ ^'3c%&Zf3
public: rr#nBhh8
int data_; ?Y"%BS+pt
}; MA
.;=T
\, R;
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! ?(ORk|)kU
(MGgr
二、类中union的初始化 !h?HfpYv
T//xxH]w-
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: gP_N|LuF"
{Y~>&B5
#pragma warning(disable : 4786) .W]k8N E
#include ]V"P
&;m
&'6/H/J
using namespace std; _k:8ib2TQ
sx?IIFF
class TestUnion 6Bq_<3P_
{ T Q41i/{
enum StoreType{Long,Const_CharP}; 7hJX
union ns~]a:1yh
{ ni;)6,i
const char* ch_; @$
7 GrT
long l_; rHKO13WF
} data_; zPnb_[YF
StoreType stype_; 8AR8u!;8
TestUnion(TestUnion&); _[rFnyC+0V
TestUnion& operator=(const TestUnion&); Bx45yaT
public: BX/3{5Y>{
TestUnion(const char* ch); luP;P&
TestUnion(long l); /r4l7K
operator const char*() const {return data_.ch_;} E#!N8fQ
operator long() const {return data_.l_;} y:)^*2GA-B
}; cWW?@_
b8d0]YS
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) |]-Zz7N)
{ kQkc+sGJf
} @gN"Q\;F
SKC;@?
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) ZLjAhd)
{ [9sEc
} 5L3+KkX@
[ar0{MPYd
int main (void) j(%N.f6
{ 4Y(@
KUb
TestUnion pszobj("yuankai"); &tH?m;V
TestUnion lobj(1234); ]g-%7g|
cout<(pszobj)< cout< i~h@}0WR"
return 0; VcKB:(:[
} 6f +aGz
zT>!xGTu7~
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: d-b04Q7DQ
=TD`P et
class TestUnion 3en9TB
{ m,)s8_a
enum StoreType{Long,Const_CharP}; @HS*%N"*
union DataUnion //不能匿名 _:Qh1 &h
{ F` ybe\
DataUnion(const char*); //声明const char*构造函数 @jn&Wf?
DataUnion(long); //声明long构造函数 ! AwMD
const char* ch_; Na91K4r#
long l_; dJR[9T_OF
} data_; vIpL8B86a
StoreType stype_; wsmgkg
TestUnion(TestUnion&); (H_dZL
TestUnion& operator=(const TestUnion&); [[|#}D:L
public: 9w-\K]
TestUnion(const char* ch); M5no4P<
TestUnion(long l); "'CvB0>
operator const char*() const {return data_.ch_;} P3"R2-
operator long() const {return data_.l_;} Qxz[
}; L"ho|v9:
2Wzx1_D"a
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) mn@1c4y
{//注意data_(ch),这里直接引用data_ S"!6]!~^
} 9d"*Z%!j
dWd%>9}
TestUnion::TestUnion(long l):data_(l),stype_(Long) ?TA7i b_
{//注意data_(l),这里直接引用data_ ^$ Y9.IH"
} +0Q
[S'1OR$FQ\
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) *duG/?>P
{ TKnWhB/J
} ]0D- g2!|A
<%^/uS
TestUnion::DataUnion::DataUnion(long l):l_(l) ZSu.0|0#
{ KZ2[.[(Ph
} PMP{|yEx"
O_;BZzT
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!