类是一种导出数据类型,或称用户自定义的数据类型,定义类之后,就可以用它来说明变量,具有类类型的变量称为类的对象,或称为类的实例。在程序中定义对象的语法和定义变量相同。
7.1.2.1 对象的创建
定义对象的方法,一般格式为: 〈〈存储类型〉〉 〈类名〉〈对象名1〉〈〈,〈对象名2〉,---〉〉; 〈〈存储类型〉〉:指定了对象的存储类型,是可选的,默认为自动(auto)类型 〈类名〉: 为用户自定义类的名字; 〈对象名〉: 是所要创建的对象的名字,它可为任意的合法的标识符。 例如:可用例9.1中的类CDate创建如下的两个对象: 1. CDate t1 , t2 ;
2. 在定义类的同时创建对象: Class CCreate {
int x , y ;
public:
void Print ( void)
{ cout< } r1 , r2 ; //定义类的同时定义对象 3.在创建对象的同时允许对它的公有成员数据用一种特殊方式进行初始化,称为初始化列表法。注意,不允许用这种方式,对对象的私有或保护成员函数进行初始化。 class { public : int x , y ; } x1 ,x2={58 ,68} ; //不定义类名,直接创建对象,对第二个对象初始化 4.在创建对象时,编译系统只为对象中的成员数据分配存储空间。而同类对象的成员函数的代码却是共享,即将类的成员函数的代码被存放到一个公用区中,为该类所有的对象所共用,而不是为每一个对象复制一份成员函数的代码,这样就节省了大量的内存空间。 7.1.2.2 对象的使用 对象只能访问公有成员。一般格式: 〈对象名〉·〈公有成员数据名〉 或 〈对象名〉·〈公有成员函数名〉( 〈参数表〉) “· ”称为成员选择运算符。 访问对象的成员函数也称为向对象发送一个消息。 只能访问公有成员,而不能访问私有成员或保护成员。对象只能通过公有成员函数间接地访问其私有成员或保护成员。 例7.1.3 (P227)定义一个描述线段的类,要求能够设置该线段,并能获取其坐标值以及该线段的长度。 # include float x1 , y1 ; 6 public: float x2 ,y2 ; public: void SetCoord ( float , float ,float ,float) ;//设置坐标值函数 float GetCoordX1( ) { return x1; } //获取第一个端点的横坐标 float GetCoordY1() {return y1 ;} //获取第一个端点的纵坐标 void Print ( void ) { float L ; L=sqrt((y2-y1) *(y2-y1)+(x2-x1)(x2-x1)) ; cout<<“该直线的长度为:”< void Cline ::SetCoord ( float a1 , float b1 ,float a2 ,float b2) {x1= a1 ; y1=b1 ; x2=a2 ; y2=b2 ; } void main (void ) { Cline line1 ,line2 ; line1·SetCoord(50,60,100,200) ; cout<<”x1=”< line2=line1 ; //c line2·Print ( ) ; } 运行程序的结果: x1=50 y1=60 x2=100 y2=200 该直线的长度为:=148.661 该直线的长度为:=148.661 注意: 1)可用成员选择运算符“·”来访问对象的公有成员。 2)同类型的对象之间可以整体赋值。 3)对象可用作函数的参数,此时属于值调用;函数也可以返回一个对象。 4)一个类的对象可作为另一个类的成员,称为对象成员。 class A { --- } ; 7 Class B { A a1 ,a2 ; } ; 类B定义了私有成员a1 ,a2 ,这两个成员都是类A的对象。 7.1.2.3 对象数组和对象指针 1.数组:采用数组的形式同时定义一组同类型的对象。对象数组可以为一维,也可以为多维。 定义一维对象数组的方法与定义基本数据类型的方法类似。格式为: 《存储类型》〈类名〉〈对象数组名〉[ 〈常量表达法〉] ; 例: CDate dates[30] ; //定义一个大小为30 的CDate 类型的数组。即包含了30个CDate类型的变量。 2.与基本数据类型数组的定义不同,在说明对象数组时,不能对它进行初始化。 对象数组的元素通常是通过默认构造函数进行初始化,因此,一个类能创建对象数组的先决条件是:它必须具有不带参数或参数全部具有默认值的构造函数,或者没有定义构造函数。 3.指针类型的对象,一般格式: 《存储类型》〈类名〉*〈对象名1〉〈〈 ,*〈对象名2 〉---〉〉 ; 例:Cline *line1 , *line2 ; //指向的数据类型为CLine类型。 可以用new运算符为对象指针分配内存空间。一般格式 <对象指针名>= new 〈类名〉( 〈参数表〉 ) 这里的参数表与相应类中的某个构造函数的参数相对应。(见10章) 例: CLine *line3=new CLine ; delete line3 ; 对象指针也只能访问封装在其内部的公有成员。见230。 访问方式与结构类型的指针访问其成员的方式类似,使用运算符“->”。 格式: <对象指针名> -> <公有成员函数名>(<参数表>); 例如:对前面定义的对象指针line1 line1 -> x2= 300 ; line2 ->y2 = 400 ; line3 ->Print ( ) ; 7.1.4 *this指针 *this指针是一个指向当前被操作对象的特殊指针。*this指针可以显示地使用,但很多情况都是隐式使用。 当某个对象调用一个成员函数时,系统将自动为该函数指定一个隐含的参数,该参数是一个指向该对象的指针,这个指针就是*this指针。 *this具有如下形式的默认形式: <类名>*const this ;. 例7.1.4 定义一个时间类。 # include 8 { int hours ,minutes ; public: void SetTime ( int new_hours ,int new_minutes ) { hours = new_hours ;minutes = new_minutes ; } void GetTime (int ¤t_hours ,int &corrent_minutes ) { current_hours=hours ;current_minutes=minutes ; } void CopyTime ( CTime &Time2); } ; void CTime ::CopyTime (CTime &Time2) { *this=Time2; //B *this指针代表当前对象 } void main (void ) { int hrs ,mins ; CTime Time1 ,Time2 ; Time1.SetTime (10 ,30 ); Time2.SetTime (12 ,15) ; Time1.GetTime ( hrs ,mins) ; cout<<”Time is :”< cout<<”after copying Time2 to Time1,the time is :”< Time is :10 : 30 after copying Time2 to Time1,the time is :12:15 Press any key to continue */ 7.1.2.5 类实现数据的封装 面向对象的封装性主要是通过对象的封装性来体现的。 类实现了对数据的封装并不意味着用户不能修改其私有和保护成员数据,这些数据可以通过类的公有成员函数(或类的友元)加以修改。这些公有的成员函数就称为类的公共接口,它们是类与外界进行信息交换的唯一途径,所有公共接口的集合称为类的协议。 例7.1.5 设计一个CbankAccount类,用来模拟银行为客户开一个银行帐号存款并取款的过程。 在取款的函数中设有验证客户银行帐户及其存款数目是否大于取款数目的功能,如果这两个条件不能同时满足,则不能执行取款的操作。不管是哪一个顾客,他的存取都只是这个 9 类的实例化而已。(当然,一个真实的银行帐号管理软件远比这复杂)。 这里使用了构造函数,构造函数将在10章介绍。这里可以将其理解为初始函数。 #include float CBankAccount ::WithDraw(long count_num ,float amount) //取款 { if(account!=count_num) //如果输入的帐号不对 { cout<<\; return 0.0; } if(balance void main() { CBankAccount a ,b; //两个对象中的成员数据都为0 a.MakeDeposit(1001,1000); a.WithDraw(1001,500) ; a.MakeDeposit(1001,2000); a.WithDraw(1001,1000); b.MakeDeposit(1002,5000); b.WithDraw(1002 ,2000); 10 b.WithDraw(1002,8000); b.WithDraw(1003,2000); b.WithDraw(1002,2000); } 运行结果: 1001 After deposit,the balance is: 1000 1001 After witndraw,the balance is : 500 1001 After deposit,the balance is: 2500 1001 After witndraw,the balance is: 1500 1002 After deposit,the balance is: 5000 1002 After witndraw,the balance is : 3000 The amount to witndraw is bebyond the balance. Illegal account_number! 1002 After witndraw,the balance is :1000 可见,类CbankAccount中的所有成员数据都被封装起来,外部对象不能直接访问它们。但可以通过公有成员函数MakeDeposit()、WithDraw()对它们进行间接的访问。 11