编码运行环境:VS2012+Win32+Debug
Win32既表示运行平台是Windows 32bits操作系统,又表示生成32bits的应用程序。
结构体(struct)与联合体(union)是C语言中就已经存在的数据类型。C++语言对他们进行了扩充,最大的变化是允许在结构和联合体中定义成员函数。下面将通过实例讲解二者的特性和用法。
1.struct
以下是一个使用了结构的C++程序。
#include <iostream>
using namespace std;
struct Room{
int floor;
int No;
};
struct Student{
int age;
int score;
Student(int a,int s){
age=a;
score=s;
}
};
int main(int argc,char* argv[])
{
Room r[3]={{1,101},{2,201},{3,301}};
Student s(18,89);
cout<<"the room are:";
cout<<r[0].floor<<"-"<<r[0].No<<" ";
cout<<r[1].floor<<"-"<<r[1].No<<" ";
cout<<r[2].floor<<"-"<<r[2].No<<endl;
cout<<"the student‘s age:"<<s.age<<" score:"<<s.score<<endl;
getchar();
}
程序运行结果:
the room are:1-101 2-201 3-301
the student’s age:18 score:89
阅读以上程序,在C++中使用结构体(struct)要注意一下几点:
(1)C++中,结构体是一种真正的数据类型,在利用结构定义变量时,不需要像在C中带上struct关键字,或先使用typedef struct structname structalias的方式进行申明。
(2)C++对C中的struct进行了扩充,允许在struct中定义成员函数。Struct中的成员变量和长远函数也有访问权限。在class中,默认的访问权限是private,而在struct中默认访问权限是public,这是结构和类的唯一区别。Struct成员的默认访问权限设为public是C++保持与C语言兼容而采取的一项策略。
(3)如果struct中没有显示定义任何构造函数,那么结构变量可以像在C语言中那样用花括号顺序指明数据成员的值来进行初始化。但是一旦显示定义了任何一个构造函数,就不能用这种方式初始化了。如果在class中只有若干public型的数据成员,而没有显示定义任何构造函数,也可以使用花括号进行初始化。
(4)用sizeof运算符计算结构的大小时,要考虑结构体内部变量的对齐问题。
请牢记,在struct中默认访问权限是public,这是结构和类的唯一区别。
2.union
联合(union)是一种特殊的类,很少用但很有用。它是从C语言章继承而来的,其基本予以没有发生什么变化,只是具有了类的一些特性(允许定义成员函数)。与结构不同的是,联合中的数据成员共享了一段内存,以达到节省空间的目的。
2.1union的基本性质
通过如下程序考察union变量的占用空间,成员赋值时的相互影响。
#include <iostream>
using namespace std;
union testunion{
char c;
int i;
};
int main(int argc,char* argv[])
{
cout<<sizeof(testunion)<<endl;
testunion* pt=new testunion;
char* p=reinterpret_cast<char*>(pt);
for(int i=0;i<sizeof(*pt);i++)
cout<<int(p[i])<<" ";
cout<<endl;
cout<<pt->i<<endl;
pt->c=‘A‘;
cout<<pt->c<<endl;
for(int i=0;i<sizeof(*pt);i++)
cout<<int(p[i])<<" ";
cout<<endl;
cout<<pt->i<<endl;
delete pt;
getchar();
}
程序运行结果:
4
-51 -51 -51 -51
-842150451
A
65 -51 -51 -51
-842150591
可以看出,union testunion变量的体积是4,它是由两个数据成员中体积较大的一个(int)类型来决定的。对其中一个数据成员的修改,一定会同时改变所有其他数据成员的值。不过对体积较小的数据成员的修改,只会影响到该成员应该占用的那些字节,对超出部分(高位字节)没有什么影响。
2.2union的高级特性
观察如下程序。
#include <iostream>
using namespace std;
struct Student{
int age;
int score;
Student(int a,int s){
age=a;
score=s;
}
};
union testunion{
char c;
int i;
};
class someClass{
int num;
public:
void show(){
cout<<num<<endl;
}
};
union A{
char c;
int i;
double d;
someClass s;
};
union B{
char c;
int i;
double d;
B(){
d=8.9;
}
};
union{
char c;
int i;
double d;
void show(){
cout<<c<<endl;
}
}u={‘U‘};
int main(int argc,char* argv[])
{
A a={‘A‘};
B b;
cout<<a.c<<endl;
cout<<b.d<<endl;
a.s.show();
u.show();
union{
int p;
int q;
};
p=3;
cout<<q<<endl;
getchar();
}
程序运行结果:
A
8.9
65
U
3
阅读以上程序,需要注意以下几点:
(1)union可以指定成员的访问权限,默认情况下,与struct具有一样的权限(public)。
(2)union也可以定义成员函数,包括构造函数和析构函数。与struct不同的是,它不能作为基类被继承。
(3)union不能拥有静态数据成员或引用成员,因为静态数据成员实际上并不是联合体的数据成员,它无法和联合体的其它数据成员共享空间。对于引用变量,引用本质上是一个指着常量,它的值一旦初始化就不允许修改。如果联合体有引用成员,那么联合体对象一创建初始化后就无法修改,只能作为一个普通的引用使用,这就失去了联合体存在的意义。
(4)union允许其他类的对象成为自己的数据成员,但是要求该类对象所属类不能定义constructor,copy constructor,destructor,copy assignment operator, virtual function中的任意一个。如此设计时局域共享内存的考虑。
(5)如果union类型旨在定义该类的同时使用一次,以后不再使用了,那么也可以不给出union的名称。如上例中变量u就是这种情况,这中情况下,无法为该union定义构造函数。
(6)匿名联合(anonymous union),也就是给出一个不带名称的联合体的申明后,并不定义任何该union的变量,而是直接以分号结尾。严格来说,匿名联合并不是一种数据结构,因为它不能用来定义变量,它只是指明若干个变量共享一片内存单元。在上例中,对变量p的修改实际上就是修改了变量q。可以看出,尽管匿名联合中的变量,尽管被定义在一个联合申明中,他们与同一个程序块的任何其他局部变量具有相同的作用域级别。这意味着匿名联合内的成员的名称不能与同一个作用域内的其它标识符相冲突。
另外,对匿名联合还存在如下限制:
- 匿名联合不允许有成员函数;
- 匿名联合也不能包含私有或者保护成员;
- 全局匿名联合中的成员必须是全局或静态变量。
参考文献
[1]C++高级进阶教程.陈刚.武汉大学出版社
版权声明:本文为博主原创文章,未经博主允许不得转载。