第7章类和对象内容摘要:

引用是变量的别名。 为对象建立引用时 , 程序中应该用另一个对象的名字来初始化它 , 自此 , 引用作为目标对象的别名 , 对引用的改动 , 实际上就是对目标对象的改动。 定义 p是类 Point的对象的引用 , 初始化为引用 Point对象 A, 这里要求 A已经有定义 , 而引用 p仅仅是它的别名。 引用不是值,不占存储空间,定义引用时,目标对象的存储不会改变。 分析右边程序,观察程序中对象引用的定义和使用。 include class M{ int x , y。 public: M( ){x = y = 0。 } M(int i ,int j){ x = i。 y = j。 } void Setxy(int i, int j){ x = i。 y = j。 } void print( ){coutx”,”yendl。 } }。 void main( ){ M p(3, 4)。 // 定义类 M的对象 p M amp。 q = p。 // 定义对象 p的引用 q ( )。 // 通过对象调用成员函数 ( )。 // 通过对象引用 q调用成员函数 (10,15)。 //通过对象引用 q调用成员函数 ( )。 ( )。 } 程序输出: 3, 4 3, 4 10, 15 10, 15 说明:类 M的对象 p和 p的引用 q。 从程序输出结果中可看出:对 q的操作实际上是对 p的操作。 因此: (10,15) 等价于 (10,15)。 对象指针和引用作函数参数 (1) 对象名作函数参数 对象可以作为参数传递给函数 , 其方法与普通变量作函数参数相同。 在向函数传递对象时 , 是通过传值调用传递给函数的 , 也就是说把对象的拷贝而不是对象本身传给函数。 因此函数中对对象的任何修改均不影响调用函数的对象本身。 include class A{ int a。 public: A(int i) { a = i。 } void Seta(int n) { a = n。 } int Geta( ) {return a。 } }。 void Sqra( A ob) //类 A对象做函数形参 { (( ) * ( ))。 cout”the copy of ob has a value of:”( )endl。 } void main( ) { A r(10)。 // 定义类 A的对象 Sqra( r )。 // 调用 Sqra( ) 函数 , 实参是对象 r cout”the value of the r has a value of:”( )endl。 } 例 :对象名作函数参数 执行程序 , 输出结果如下: the copy of ob has a value of: 100 the value of the r has a value of : 10 (2 ) 对象指针作函数参数 同其它类型变量一样 , 也可以将对象地址传递给函数 , 即使用对象指针作为函数形参 , 并且这比使用对象作函数参数更普遍一些。 因为使用对象指针作函数参数有如下两点好处: ( 1) 实现传址调用。 可在被调用函数中改变调用函数的参数对象的值 , 实现对象之间的信息传递。 ( 2) 实参仅将对象的地址值传递给形参 , 而不进行副本的拷贝 , 这样可以提高程序运行效率 , 减少时空开销。 对象指针作函数形参时 , 要求调用函数的实参是对象的地址值。 include class A{ int x,y。 public: A( ) {x = y = 0。 } A(int i, int j ) {x = i。 y = j。 } void copy( A * p) { x = px。 y = py。 } //指针作成员函数 copy( )的形参 void Setxy( int i, int j) {x = i。 y = j。 } void print( ) {coutx”,”yendl。 } }。 void f (A a1, A *a2) //第一个形参是对象 ,第二个形参是对象指针 { (5,6)。 a2Setxy(2,5)。 } 例 对象指针作函数参数 void main() { A a(3,4),b。 (amp。 a)。 ()。 ()。 f(a, amp。 b)。 //实参对象 a对应于对象形参a1,对象 b的地址 amp。 b对应于对象指针形参 ()。 ()。 } 程序运行结果如下: 3,4 3,4 3,4 2,5 (3) 对象引用作函数参数 对象引用作函数参数具有用对象的指针作函数参数的优点 , 能达到传地址调用的效果 , 而且对象引用作函数参数将更简单 、 更直接 , 因此 , 在实际应用中。 使用对象引用作函数参数要比使用对象指针作函数参数更普遍。 include class A{ int x,y。 public: A( ) {x = y = 0。 } A(int i ,int j ) {x = i。 y = j。 } void copy( A amp。 p) { x =。 y =。 } //对象引用作成员函数 copy( )的形参 void Setxy( int i, int j) {x = i。 y = j。 } void print( ) {coutx”,”yendl。 } }。 void f (A a1, A amp。 a2) //第一个形参是对象 ,第二个形参是对象引用 { (5,6)。 (2,5)。 } 例 对象引用作函数参数 void main() { A a(3,4),b。 (a)。 ( )。 ( )。 f(a,b)。 //实参对象 a对应于对象形参 a1,实参对象 b对应于对象引用形参 ( )。 ( )。 } 运行结果如下: 3,4 3,4 3,4 2,5 对象数组 (1) 对象数组的定义 对象数组是指数组元素为对象的数组。 这种数组与普通数据类型的数组相比 ,特殊之处在于数组元素是某个类的对象 , 不仅具有数据成员 , 而且还具有函数成员。 对象数组的定义格式为: 类名 数组名 [下标 1][下标 2]… 其中,类名指出该数组元素对象所属的类,例如: Point point1[5]; Point point2[2][3] ; 与普通类型数组一样 , 对象数组可以在定义时赋初值 , 也可以在程序中被赋值。 只是赋初值和赋值的方法不同于普通数组。 下面是一个对象数组定义和赋值的例子。 class Date { int year, month, day。 public: Date ( ) {year = month = day = 0。 } Date ( int y , int m , int d ) {year = y。 month = m。 day = d。 } void print ( )。 }。 void main( ){ Date dates[4]={Date(2020,11,8), Date(1999,10 ,12) }。 dates[2]=Date (1998,8,9)。 dates[3]=Date(1999,9,10)。 for(int i=0。 i4。 i++) dates[i].print ( )。 } 的赋值 class Point{ int x,y。 public: Point(){x = y = 0。 } Point(int a,int b){x = a。 y = b。 } void print()。 }。 void main() { Point point[2][3]。 // point是二维对象数组 for(int i=0。 i2。 i++) // 通过双重 for循环给 point对象数组各元素赋值 for(int j=0。 j3。 j++) point[i][j]=Point(i+10, j+15)。 Point (*p)[3](point)。 //定义一个指向一维对象数组的指针 p, //并用数组名 point进行初始化 , 使指针 p指向数组 point for( i=0。 i2。 i++) //双重循环将 p指针所指向的数组元素进行输出 { for(int j=0。 j3。 j++) (*(*(p+i)+j)).print()。 coutendl。 } } (2) 指向对象数组的指针 指向对象数组的指针定义格式为: 类名 ( *〈 指针名 〉 ) [下标说明 ] 例如: Date (*pd)[4]。 //pd是指向一维对象数组的指针 , 该数组元素是 Date类的对象。 include class A{ int a,b。 public: A(){ a=0。 b=0。 } A(int x, int y){ a = x。 b = y。 } void print( ) { couta, bendl。 } }。 void main( ) { A a1(3,4), a2(8,9), a3。 A *pa[3]={ amp。 a1, amp。 a2, amp。 a3 }。 for(int i=0。 i3。 i++) pa[i]print( )。 } (3) 对象指针数组 执行该程序输出如下: 3, 4 8, 9 0, 0 对象指针数组的所有元素都是指向同一个类的对象的指针。 其声明格式如下: 类名 *数组名 [下标 ]… 在内存的堆区中创建和删除对象 , 使用 new运算符和 delete运算符。 用 new运算符动态创建对象的语法格式为: 对象指针 = new 类名 ( 初始值列表 ) ; 该语句在程序运行过程中调用类的构造函数为对象的数据成员分配内存空间并为它们赋初值 , 然后返回一个指向新创建对象的指针。 此后在程序中就可以通过该指针访问此动态创建的对象。 例如: Point* ptr。 ptr = new Point(, )。 全局数据区 代码区 堆区 栈区 C++ 的内存布局 动态对象 由于用 new 分配内存不一定总能成功,比如没有足够的内存空间或供分配等。 此时 new 操作将返回一个空指针( NULL)。 如果没有注意到 new操作失败而去使用对象指针将会发生无法估计的后果。 所以通常在每次 new 操作后应写一段程序检查 new 是否成功 :。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。