第3 章 怎样使用类和对象   通过第2 章的学习,已经对类和对象有了初步的了解。在本章中将进一步说明怎样 使用类和对象。本章将会遇到一些稍复杂的概念,我们尽量用读者容易理解的方式进行 介绍,也请读者细心阅读。 3.1 类对象的初始化 3.1.1 需要对类对象进行初始化   在程序中常常需要对变量赋初值,即对其初始化。这在面向过程的程序中是很容易 实现的,在定义变量时赋以初值。如   int a=10;          //定义整型变量a,a 的初值为10 在基于对象的程序中,在定义一个对象时,有可能需要作初始化的工作,包括对数据成员 赋初值。对象代表一个实体,每一个对象都有它确定的属性。例如有一个Time 类(时 间),用它定义对象t1,t2,t3。显然,t1,t2,t3 分别代表3 个不同的时间(时、分、秒)。每 一个对象都应当在它建立之时就有确定的内容,否则就失去对象的意义了。在系统为对 象分配内存时,应该同时对有关的数据成员赋以初始值。 那么,怎样使它们得到初值呢? 有人企图在声明类时对数据成员初始化。如   class Time  { hour=0; //不能在类声明中对数据成员初始化 minute=0; sec=0; }; 这是错误的。因为类并不是一个实体,而是一种抽象类型,并不占存储空间,显然无处容 纳数据。 如果一个类中所有的成员都是公用的,则可以在定义对象时对数据成员进行初始 化。如   class Time  { public: //声明为公用成员  72  hour; minute; sec; }; Time t1={14,56,30}; //将t1 初始化为14:56:30 这种情况和结构体变量的初始化是类似的,在一个花括号内顺序列出各公用数据成员的 值,两个值之间用逗号分隔。但是,如果数据成员是私有的,或者类中有private 或 protected 的数据成员,就不能用这种方法初始化。 在第2 章的几个例子中,是用成员函数来对对象中的数据成员赋初值的(例如例2.3 中的set_time 函数)。从例2.3 中可以看到,用户在主函数中调用set_time 函数来为数据 成员赋值。如果对一个类定义了多个对象,而且类中的数据成员比较多,那么程序就显得 非常臃肿烦琐,这样的程序哪里还有质量和效率? 应当找到一种方便的方法对类对象中 的数据成员进行初始化。 3.1.2 用构造函数实现数据成员的初始化 在C++程序中,对象的初始化是一个重要的问题。不应该使程序员在这个问题上花 费过多的精力,C++在类的设计中提供了较好的处理方法。 为了解决这个问题,C++提供了构造函数(constructor)来处理对象的初始化。构造 函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对 象时自动执行。构造函数的是在对类进行声明的时候由类的设计者定义的,程序用户只 须在定义对象的同时指定数据成员的初值即可。 构造函数的名字必须与类名同名,而不能任意命名,以便编译系统能识别它,并把它 作为构造函数处理。它不具有任何类型,不返回任何值。 先观察下面的例子。 例3.1 在例2.3 基础上,用构造函数为对象的数据成员赋初值。 编写程序:   #include using namespace std; class Time      //声明Time 类  {public: //以下为公用函数  Time() //定义构造成员函数,函数名与类名相同  {hour=0; //利用构造函数对对象中的数据成员赋初值 minute=0; sec=0; } void set_time(); //成员函数声明 void show_time(); //成员函数声明 private: //以下为私有数据  int hour; int minute;  73 int sec;  }; void Time::set_time() //定义成员函数,向数据成员赋新值  {cin>>hour; cin>>minute; cin>>sec; } void Time::show_time() //定义成员函数,输出数据成员的值  { cout< using namespace std; class Box             //声明Box 类  {public:  Box(int,int,int); //声明带参数的构造函数 int volume(); //声明计算体积的函数 private:  int height; //高 int width; //宽 int length; //长 }; Box::Box(int h,int w,int len) //在类外定义带参数的构造函数  {height=h; width=w; length=len; } int Box::volume() //定义计算体积的函数  {return(height.width.length); } int main()  {Box box1(12,25,30); //建立对象box1,并指定box1 的高、宽、长的值 cout<<"The volume of box1 is "< using namespace std; class Box  {public:  Box();           //声明一个无参的构造函数Box Box(int h,int w,int len):height(h),width(w),length(len){ } //定义一个有参的构造函数,用参数的初始化表对数据成员初始化 int volume();        // 声 明成员函数volume private:  int height; int width; int length; };  78 Box::Box() //在类外定义无参构造函数Box  {height=10; width=10; length=10; } int Box::volume() //在类外定义成员函数volume  {return(height.width.length); } int main()  {Box box1; //建立对象box1,不指定实参 cout<<"The volume of box1 is "< using namespace std; class Box  {public:  Box(int h=10,int w=10,int len=10); //在声明构造函数Box 时指定默认参数 int volume(); private:  int height; int width; int length; }; Box::Box(int h,int w,int len) //在定义Box 函数时可以不指定默认参数  {height=h; width=w;  80 length=len; } int Box::volume()  {return(height.width.length); } int main()  { Box box1; //没有给定实参 cout<<"The volume of box1 is "< #include using namespace std; class Student                 //声明Student 类  {public:  Student(int n,string nam,char s) //定义有参数的构造函数 {num=n; name=nam; sex=s; cout<<"Constructor called."< using namespace std; class Box  {public:  Box(int h=10,int w=12,int len=15) :hetght(h),width(w),length(len){} //声明有默认参数的构造函数,用参数初始化表对数据成员初始化 int volume(); private:  int height; int width; int length;  89 }; int Box::volume()  {return(height.width.length); } int main()  { Box a[3]={          //定义对象数组  Box(10,12,15), //调用构造函数Box,提供第1 个元素的实参 Box(15,18,20), //调用构造函数Box,提供第2 个元素的实参 Box(16,20,26) //调用构造函数Box,提供第3 个元素的实参 Return 0; }; cout<<"volume of a[0] is "<hour //pt 所指向的对象中的hour 成员,即t1.hour (.pt).get_time() //调用pt 所指向的对象中的get_time 函数,即t1.get_time pt->get_time() //调用pt 所指向的对象中的get_time 函数,即t1.get_time 上面第2,3 两行的作用是等价的,第4,5 两行也是等价的。 3.3.2 指向对象成员的指针 对象有地址,存放对象的起始地址的指针变量就是指向对象的指针变量。对象中的 成员也有地址,存放对象成员地址的指针变量就是指向对象成员的指针变量。 1. 指向对象数据成员的指针 定义指向对象数据成员的指针变量的方法和定义指向普通变量的指针变量方法相 同。例如   int .p1; //定义指向整型数据的指针变量 定义指向对象数据成员的指针变量的一般形式为   数据类型名.指针变量名; 如果Time 类的数据成员hour 为公用的整型数据,则可以在类外通过指向对象数据成员 的指针变量访问对象数据成员hour:   p1=&t1.hour; //将对象t1 的数据成员hour 的地址赋给p1,使p1 指向t1.hour cout<<.p1<