- 内容提要
- 前言
- 第 1 章 预备知识
- 第 2 章 开始学习 C++
- 第 3 章 处理数据
- 第 4 章 复合类型
- 第 5 章 循环和关系表达式
- 第 6 章 分支语句和逻辑运算符
- 第 7 章 函数——C++的编程模块
- 第 8 章 函数探幽
- 第 9 章 内存模型和名称空间
- 第 10 章 对象和类
- 第 11 章 使用类
- 第 12 章 类和动态内存分配
- 第 13 章 类继承
- 第 14 章 C++中的代码重用
- 第 15 章 友元、异常和其他
- 第 16 章 string 类和标准模板库
- 第 17 章 输入、输出和文件
- 第 18 章 探讨 C++新标准
- 附录 A 计数系统
- 附录 B C++保留字
- 附录 C ASCII 字符集
- 附录 D 运算符优先级
- 附录 E 其他运算符
- 附录 F 模板类 string
- 附录 G 标准模板库方法和函数
- 附录 H 精选读物和网上资源
- 附录 I 转换为 ISO 标准 C++
- 附录 J 复习题答案
10.4 this 指针
对于 Stock 类,还有很多工作要做。到目前为止,每个类成员函数都只涉及一个对象,即调用它的对象。但有时候方法可能涉及到两个对象,在这种情况下需要使用 C++的 this 指针。
虽然 Stock 类声明可以显示数据,但它缺乏分析能力。例如,从 show( ) 的输出我们可以知道持有的哪一支股票价格最高,但由于程序无法直接访问 total_val,因此无法作出判断。要让程序知道存储的数据,最直接的方式是让方法返回一个值。为此,通常使用内联代码,如下例所示:
就直接程序访问而言,上述定义实际上是使 total_val 为只读的。也就是说,可以使用方法 total_val( ) 来获得 total_val 的值,但这个类没有提供专门用于重新设置 total_val 的值的方法(作为一种副产品,其他方法,如 buy( )、sell( ) 和 update( ) 确实在重新设置成员 shares 和 share_val 的值的同时修改了 total_val 的值)。
通过将该函数添加到类声明中,可以让程序查看一系列股票,找到价格最高的那一支。然而,可以采用另一种方法——一种帮助您了解 this 指针的方法。这种方法是,定义一个成员函数,它查看两个 Stock 对象,并返回股价较高的那个对象的引用。实现这种方法时,将出现一些有趣的问题,下面就来讨论这些问题。
首先,如何将两个要比较的对象提供给成员函数呢?例如,假设将该方法命名为 topval( ),则函数调用 stock1.topval( ) 将访问 stock1 对象的数据,而 stock2.topval( ) 将访问 stock2 对象的数据。如果希望该方法对两个对象进行比较,则必须将第二个对象作为参数传递给它。出于效率方面的考虑,可以按引用来传递参数,也就是说,topval( ) 方法使用一个类型为 const Stock &的参数。
其次,如何将方法的答案传回给调用程序呢?最直接的方法是让方法返回一个引用,该引用指向股价总值较高的对象。因此,用于比较的方法的原型如下:
该函数隐式地访问一个对象,而显式地访问另一个对象,并返回其中一个对象的引用。括号中的 const 表明,该函数不会修改被显式地访问的对象;而括号后的 const 表明,该函数不会修改被隐式地访问的对象。由于该函数返回了两个 const 对象之一的引用,因此返回类型也应为 const 引用。
假设要对 Stock 对象 stock1 和 stock2 进行比较,并将其中股价总值较高的那一个赋给 top 对象,则可以使用下面两条语句之一:
第一种格式隐式地访问 stock1,而显式地访问 stock2;第二种格式显式地访问 stock1,而隐式地访问 stock2(参见图 10.3)。无论使用哪一种方式,都将对这两个对象进行比较,并返回股价总值较高的那一个对象。
图 10.3 使用成员函数访问两个对象
实际上,这种表示法有些混乱。如果可以使用关系运算符>来比较这两个对象,将更为清晰。可以使用运算符重载(参见第 11 章)完成这项工作。
同时,还要注意的是 topval( ) 的实现,它将引发一个小问题。下面的部分实现强调了这个问题:
其中,s.total_val 是作为参数传递的对象的总值,total_val 是用来调用该方法的对象的总值。如果 s.total_val 大于 toatl_val,则函数将返回指向 s 的引用;否则,将返回用来调用该方法的对象(在 OOP 中,是 topval 消息要发送给的对象)。问题在于,如何称呼这个对象?如果调用 stock1.topval(stock2),则 s 是 stock2 的引用(即 stock2 的别名),但 stock1 没有别名。
C++解决这种问题的方法是:使用被称为 this 的特殊指针。this 指针指向用来调用成员函数的对象(this 被作为隐藏参数传递给方法)。这样,函数调用 stock1.topval(stock2)将 this 设置为 stock1 对象的地址,使得这个指针可用于 topval( ) 方法。同样,函数调用 stock2.topval(stock1)将 this 设置为 stock2 对象的地址。一般来说,所有的类方法都将 this 指针设置为调用它的对象的地址。确实,topval( ) 中的 total_val 只不过是 this->total_val 的简写(第 4 章使用->运算符,通过指针来访问结构成员。这也适用于类成员)(参见图 10.4)。
注意:
每个成员函数(包括构造函数和析构函数)都有一个 this 指针。this 指针指向调用对象。如果方法需要引用整个调用对象,则可以使用表达式*this。在函数的括号后面使用 const 限定符将 this 限定为 const,这样将不能使用 this 来修改对象的值。
然而,要返回的并不是 this,因为 this 是对象的地址,而是对象本身,即*this(将解除引用运算符*用于指针,将得到指针指向的值)。现在,可以将*this 作为调用对象的别名来完成前面的方法定义。
图 10.4 this 指向调用对象
返回类型为引用意味着返回的是调用对象本身,而不是其副本。程序清单 10.7 列出了新的头文件。
程序清单 10.7 stock20.h
程序清单 10.8 列出了修订后的类方法文件,其中包括新的 topval( ) 方法。另外,现在您已经了解了构造函数和析构函数的工作原理,因此这里没有显示消息。
程序清单 10.8 stock20.cpp
当然,我们想知道 this 指针是否有用。显然,应在一个包含对象数组的程序中使用这种新方法。因此接下来介绍对象数组这一主题。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论