前言 ST*h{:u&A
gF{ehU%
熟悉C的程序员都知道union(联合体)的用法,利用union可以用相同的存储空间存储不同型别的数据类型,从而节省内存空间。当访问其内成员时可用"."和"->"来直接访问。在C++出现后,它继承了union并保留了其在C中的特性。但是在C++中的union又有了新的扩展,这需要大家了解,要不然你会感到费解和迷惑。下面我讲两点。 S/'0czDMW
a;HAuy`M x
一、在union中存储对象 E5&Z={
:(n<c
在C中union中可以存储任意类型的内置数据类型,那么在C++中union是否可以存储对象呢?还是让我们看一个例子吧,这比任何言语都能说明问题,不是吗? I}4
PB+yu
=Z^5'h~
#pragma warning(disable : 4786) Y@+Rb
#include ;5 j|B|v
using namespace std; %":3xj'EEI
IL].!9
class TestUnion _uQ]I^ 'D
{ 1INX#qTZ
public: z'q~%1t
TestUnion(long l):data_(l) OIrm9D#
{ kv:9Fm\$
}; ENTcTrTn
int data_;
,&hv x
}; V.GM$
!=dz^f.{
typedef union _tagUtype_ $o[-xNn1
{ i HD!v7d7
TestUnion obj; 2LwJ%!
}UT; ]@&X*~c^Z
DK IH{:L7
int main (void) Ei4^__g\'
{ <7^|@L
6
return 0; ic2D$`M
} u&:N`f
=l`)b
y(COB6r
这样不行,union中不可以存储TestUnion类的对象,但在C中union可以存储struct呀,为什么不能存储类的对象呢?很简单,请问,在C中union可以存储带有构造函数的struct吗?对了,在C中的struct是没有构造函数的。所以如果C++中union可以存储有构造函数的类的对象就不太符合逻辑,那不是说C++和C完全兼容吗?不错,正因为这一点,C++中union不可以存储有构造函数的类的对象,但是可以存储不带构造函数的类的对象,这样就和C保持一致了,不想信你试试。对TestUnion类的声明进行如下修改: Pd91<L
z#tIa
class TestUnion iq; |
i!
{ C*Vm}|)
public: {D4FYr
J
int data_; {*yvvb
}; 0JlNUO5Nt
9-42A7g^C
再进行编译,一切OK!。但是这样却失去了C++的构造初始化特性,这样做是没有任何意义的,我只是在说其在C++中的语义,并不是推荐大家使用(绝对不推荐)。但是我们可以在union中存储对象的指针,从而引用不同的对象类型。不用我再多说了吧,大家还是试试吧! F9r.DG$}
&6x(%o|
二、类中union的初始化 g*V.u]U!i
(T%F^s5D
由于union的共享内存特点,我们可以使我们的类存储不同的型别而不浪费内存空间,在类中我们可以声明一个union存储不同型别的指针,示例如下: 1q}LO2
V:n0BlZ,B
#pragma warning(disable : 4786) a"vzC$Hxd
#include Lw>B:3e
[6!k:-t+
using namespace std; $Rm~ VwY#
Fw<"]*iu
class TestUnion @Q74
{ *S;}&VAZ
enum StoreType{Long,Const_CharP}; 7V"?o
union W'./p"2g
{ @>8(f#S%
const char* ch_; 7Nq<
o5
long l_; >tM4|w|
} data_; @;/Pl>$|'G
StoreType stype_; \"O5li3n
TestUnion(TestUnion&); X=sE1RB
TestUnion& operator=(const TestUnion&); >XgoN\w
public: ]rG=\>U3~
TestUnion(const char* ch); {T4_Xn -I
TestUnion(long l); /@9Q:'P
operator const char*() const {return data_.ch_;} 7
Lm9I
operator long() const {return data_.l_;} :5k* kx#y
}; q[$>\Nfg>B
=3bk=vy
TestUnion::TestUnion(const char* ch):data_.ch_(ch),stype_(Const_CharP) ;8]HCC@:
{ |;gx;qp4cN
} EG{+Sz
n`5Nf
TestUnion::TestUnion(long l):data_.l_(l),stype_(Long) B"4 3o7C
{ x"2p5T7*>
} _^<vp
Cd%5XD^
int main (void) ,
'pYR]3
{ tiK M+
;C
TestUnion pszobj("yuankai"); bQaRl=:[:
TestUnion lobj(1234); Jq_\r'YE
cout<(pszobj)< cout< S@,/$L
return 0; B7\4^6Tx
} P27Ot1px
.}dLqw
真是不幸,编译都通不过,好象没有什么问题呀,为什么呢?data_.ch_(ch)和data_.l_(l)有问题吗?如果你问一个C程序员他会告诉你,绝对没问题。你不会去怀疑编译器有问题吧!不好意思!我一开始就是这么想的,真是惭愧。费解,迷惑。让我们来看看构造TestUnion对象时发生了什么,这样你就会明白了。当创建TestUnion对象时,自然要调用其相应的构造函数,在构造函数中当然要调用其成员的构造函数,所以其要去调用union成员的构造函数,但是其为匿名的,有没有构造函数可调用,所以出错。很明显在C++中union和class一样它可以有构造函数,不能如此直接引用其成员。struct同样有这限制。只要我们给其定义一个构造函数什么问题都解决了。示例如下: o-<i+ To%
yhH2b:nY(9
class TestUnion uX7L1~s-
{ c~T{;
enum StoreType{Long,Const_CharP}; :w^:Z$-hf
union DataUnion //不能匿名 Q7+WV`&
{ KMhrw s{&B
DataUnion(const char*); //声明const char*构造函数 7ZUN;mr
DataUnion(long); //声明long构造函数 0F$|`v"0
const char* ch_; | R,dsBd
long l_; RZz?_1'
} data_; Il=6t
StoreType stype_; 2"6L\8hd2
TestUnion(TestUnion&); >{^_]phlb
TestUnion& operator=(const TestUnion&); QytO0K5
public: neEqw+#Z
TestUnion(const char* ch); BValU
TestUnion(long l); X_PzK'#m
operator const char*() const {return data_.ch_;} DwBe_h .
operator long() const {return data_.l_;} OS[
s Qo5
}; 2f(`HSC'
f}c;s
TestUnion::TestUnion(const char* ch):data_(ch),stype_(Const_CharP) `q}D#0
{//注意data_(ch),这里直接引用data_ LW=qX%o{
} SqAz((
nDkG}JkB!
TestUnion::TestUnion(long l):data_(l),stype_(Long) (Q{JI~P
{//注意data_(l),这里直接引用data_ 5 H._Q
} 6C$+D
@5Z|e
TestUnion::DataUnion::DataUnion(const char* ch):ch_(ch) {V[xBL
<
{ |]kiH^Ap
} U`*we43
_kD5pC =
TestUnion::DataUnion::DataUnion(long l):l_(l) lg|6~=aQ
{ X"Eqhl<t
} SrA6}kS
as:=QMV
现在再编译,如果还不行,你怀疑编译器有问题是有理由的。好了就写这么多吧!希望对大家有帮助,我可是花了一个下午的时间呀!