大家好,欢迎来到IT知识分享网。
6.1 对象指针和对象引用
第6章 类和对象(二)
前一章中讲述了类和对象的一些基础知识,本章将进一步讨论类和对象的其他方面的内容。这些内容包括指针和引用在类和对象中的应用,使用 new 和 delete 运算符对对象进行动态分配和释放等。本章通过一些实例来深入理解类和对象在编程中的应用。
6.1 对象指针和对象引用
本节讲述指向对象的指针和对象的引用这两个概念及其在 C++ 编程中的应用。在讨论这两个概念之前,先介绍指向类的成员的指针。虽然它们都是指针,但指向的目标不同。
6.1.1 指向类的成员的指针
在 C++ 中,指向类成员的指针包括指向类的数据成员和指向成员函数的指针。
指向数据成员的指针格式如下:
<类型说明符> <类名>::* <指针名>
指向成员函数的指针格式如下:
<类型说明符> (<类名>::*<指针名>)(<参数表>)
例如,定义一个类 A 如下:
class A { public: int fun(int b) { return a * c + b; } A(int i) { a = i; } int c; private: int a; };
定义一个指向类 A 的数据成员 c 的指针 pc,其格式如下:
int A::*pc = &A::c;
因为 c 是公有成员,因此可以这样定义。这里 pc 是指向 A 类的数据成员 c 的指针。
再定义一个指向类 A 的成员函数 fun 的指针 pfun,其格式如下:
int (A::*pfun)(int) = &A::fun;
使用这类指针时,需要首先指定 A 类的一个对象,然后通过对象来引用指针所指向的成员。例如,给 pc 指针所指向的数据成员 c 赋值 8,可以表示如下:
A a; a.*pc = 8;
其中,运算符 .* 用于通过指向类成员的指针来操作该类对象的成员。
使用指向对象的指针通过指向类成员的指针对该成员进行操作时,可使用运算符 ->*。例如:
A* p = &a; p->*pc = 8;
代码示例
下面是一个使用指向类成员指针的例子:
#include <iostream> class A { public: A(int i) { a = i; } int fun(int b) { return a * c + b; } int c; private: int a; }; void main() { A x(8); int A::*pc = &A::c; x.*pc = 3; int (A::*pfun)(int) = &A::fun; A* p = &x; std::cout << (p->*pfun)(5) << std::endl; }
执行该程序输出结果如下:
29
说明
- 该程序中定义了一个指向类的数据成员的指针
pc和一个指向类成员函数的指针pfun,并对这些指针进行了赋值。 - 程序中对指向类成员的两个指针进行了引用和调用。其中:
x.*pc = 3;实际上是给对象
x的成员c赋值,等价于:x.c = 3;而
(p->*pfun)(5)是通过指向对象的指针
p来调用指向类成员函数的指针pfun,函数的实参为5。等价于:p->fun(5)也可以使用对象来调用指向类成员函数的指针所指向的成员函数。例如:
(x.*pfun)(5) - 程序中使用了两种不同的指针:一种是指向对象的指针,另一种是指向类成员的指针。虽然它们都是指针,但指向的目标不同。
p是指向类的对象,pc是指向类的数据成员,pfun是指向类的成员函数,它们在使用上不同。
6.1.2 对象指针和对象引用作为函数参数
1. 对象指针作为函数参数
使用对象指针作为函数参数比使用对象本身更为普遍。其优点如下:
- 实现传址调用:可以在被调用函数中改变调用函数的参数对象的值,从而实现函数之间的信息传递。
- 提高运行效率:使用对象指针作为形参仅将对象的地址值传给形参,而不进行对象副本的复制,减少了时空开销。
对象指针作为函数形参时,要求调用函数的实参是对象的地址值。下面通过一个例子来说明使用指向对象的指针作为函数参数的方法。
例 6.2 分析下列程序的输出结果:
#include <iostream> class M { public: M() { x = y = 0; } M(int i, int j) { x = i; y = j; } void copy(M *m); void setxy(int i, int j) { x = i; y = j; } void print() { std::cout << x << "," << y << std::endl; } private: int x, y; }; void M::copy(M *m) { x = m->x; y = m->y; } void fun(M m1, M *m2); int main() { M p(5, 7), q; q.copy(&p); fun(p, &q); p.print(); q.print(); } void fun(M m1, M *m2) { m1.setxy(12, 15); m2->setxy(22, 25); }
输出结果:
5,7 22,25
说明:
- 该程序中,有两个指向对象的指针。一个是用于成员函数
copy()的参数,另一个是用于一般函数fun()的参数。当形参是指向对象的指针时,调用函数的对应实参应该是某个对象的地址值,通常使用&符号加上对象名。 - 在
fun()函数中,有两个形参,一个是对象名,另一个是指向对象的指针名。在被调用函数中,改变了对象的数据成员值和指向对象指针的数据成员值以后,可以看到只有指向对象指针作为参数所指向的对象被改变了;而另一个以对象作为参数,形参对象值改变了,但实参对象值并没有改变。因此,该程序出现上述输出结果。这便是传址调用和传值调用的不同。
2. 对象引用作为函数参数
在实际应用中,使用对象引用作为函数参数比使用对象指针更普遍。这是因为使用对象引用作为函数参数既具有对象指针的优点,同时更简单直接。因此,C++ 编程中,人们更喜欢使用对象引用作为函数参数。
例 6.3 分析下列程序的输出结果:
#include <iostream> class M { public: M() { x = y = 0; } M(int i, int j) { x = i; y = j; } void copy(M &m); void setxy(int i, int j) { x = i; y = j; } void print() { std::cout << x << "," << y << std::endl; } private: int x, y; }; void M::copy(M &m) { x = m.x; y = m.y; } void fun(M m1, M &m2); int main() { M p(5, 7), q; q.copy(p); fun(p, q); p.print(); q.print(); } void fun(M m1, M &m2) { m1.setxy(12, 15); m2.setxy(22, 25); }
输出结果:
5,7 22,25
说明: 将该程序与例 6.2 进行比较可以看出,主要区别在于例 6.2 中使用的指向对象的指针在例 6.3 中换成了对象引用。对象引用的使用更简洁直观,同时也具有指针的传址调用特性,从而在 C++ 编程中得到了更广泛的应用。
总结:
- 对象指针:实现传址调用,节省内存,提高效率,但需要处理指针的细节。
- 对象引用:实现传址调用,语法更简洁,避免了指针操作的复杂性,更符合面向对象编程的思想。

6.1.3 this指针
this 是一个由系统自动提供的指向对象的特殊指针。该指针是一个指向正在对某个成员函数操作的对象的指针。当对一个对象调用成员函数时,编译程序先将该对象的地址赋给系统创建的 this 指针,然后调用成员函数。每次成员函数存取数据成员时,都隐含使用 this 指针,同样也可以显式使用 *this 来标识调用该成员函数的对象。
下面通过一个例子来说明显式使用 this 指针的方法。
例 6.4 分析下列程序的输出结果,说明程序中 this 和 *this 的用法。
#include <iostream> class A { public: A() { a = b = 0; } A(int i, int j) { a = i; b = j; } void copy(const A &aa); void print() { std::cout << a << "," << b << std::endl; } private: int a, b; }; void A::copy(const A &aa) { if (this == &aa) return; *this = aa; } int main() { A a1, a2(3, 4); a1.copy(a2); a1.print(); }
输出结果:
3,4
说明:
在该程序中,类 A 的成员函数 copy() 内,出现了两次 this 指针。
- 判断自身赋值:
if (this == &aa) return;- 这段代码用于判断
this指针是否与传入的对象aa的地址相同。如果相同,则说明是自赋值,自赋值没有意义,因此直接返回。
- 这段代码用于判断
- 赋值操作:
*this = aa;- 这里的
*this表示操作该成员函数的对象,将aa对象的值赋给操作该成员函数的对象。由于this是指针,*this就是指向的对象。
- 这里的
在 main() 函数中,a1.copy(a2); 调用 copy() 成员函数,此时 this 指向 a1 对象,aa 是 a2 对象。执行 *this = aa; 语句时,将 a2 的值赋给 a1,因此 a1 的数据成员 a 和 b 被赋值为 a2 的值。
最后,调用 a1.print(); 输出结果为 3, 4。
通过这个例子,可以更好地理解 this 指针的用途,尤其是在需要处理对象自赋值和操作当前对象的情况下。




免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119080.html



