天天看点

《C++面向对象高效编程(第2版)》——3.5 this 指针和名称重整的进一步说明

本节书摘来自异步社区出版社《c++面向对象高效编程(第2版)》一书中的第3章,第3.5节,作者: 【美】kayshav dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。

c++面向对象高效编程(第2版)

在前面介绍的实现中,我们有时使用this指针访问对象的数据成员。如第2章所述,成员函数中的this指针指向调用该成员函数的对象。在前述的main()程序中,如下代码

`

a.push(i);`

通过a对象调用push成员函数。在push成员函数内部,this指针持有a对象的地址。以这样的方式,成员函数可以访问对象内的任何元素(数据成员和成员函数)。如第2章所述,编译器像实现其他函数那样,实现每个成员函数,但是,每个成员函数应该可以通过某种方法访问调用它的对象。为达到这个目的,this指针将作为隐藏的参数传递给每个成员函数,且this指针通常是函数接收的第1个参数(其后是已声明的其他参数)。假定push成员函数的实现如下:

tintstack();  // 普通的未重整名称

__ct__9tintstackfv();  // 重整后的名称<code>`</code>

同样地,此处的9tintstack仍代表this指针的类型,f表明该函数为全局函数,v表明该函数不接受任何参数(void)。

其他的构造函数(如果有的话)也会包含参数,因此,它们确切的名称应该不同。例如,复制构造函数应该是:

~tintstack();  // 未重整名称

__dt__9tintstackfv();  // 重整名称<code>`</code>

类似地,操作符函数也有经过特定编码的重整名。例如,赋值操作符被编码成:

<code>__as__9tintstack();</code>

全局new()操作符以__nw开始,全局delete操作符以__dl开始。

语言中所有的操作符都有预定义的(pre-defined)编码。

你可能会问,为什么要知道关于名称重整的这些细节?

想象一下,你实现了一个类,但忘记实现一些成员函数。编译过程可能没什么问题,但链接器会对未定义的函数报错。这些显示在报错信息中的函数,看上去与你在类头文件3中的函数不一样。现在,你彻底糊涂了!

这是因为名称重整的缘故。链接器在报错时绝不会打印原始的函数名,它只会给出由编译器提供的等价重整名。链接器对重整一无所知(至少到目前为止,我还未见过链接器了解此事),它只会抱怨那些未定义的名称。此时,如果了解一些名称重整会对你有帮助。如果链接器打印出的名称以 ct 开始,则说明出问题的是某个构造函数,这缩小了查找未定义成员函数的范围。随着你编写的c++代码越来越多,重整名称会成为你破译报错信息的秘密武器!相信我。

    

警告:

记住,this指针是个非常神圣的指针。不能修改this指针,绝不能给它赋值!需要在成员函数内修改<code>this</code>指针的情况非常少见,稍后将会介绍这样的示例。

你可能也注意到,在每个成员函数内,我们并未用this指针访问数据成员。例如,在pop函数中,无需任何限定符,即可直接访问数据成员<code>_count</code>。无论何时在成员函数中使用数据成员的名称,编译器都会为其预先添加“this”限定符。因此,<code>_count</code>成为<code>this-&gt;_count</code>。除非我们明确需要指向对象的指针,否则不必显式使用它。

样式:

在本书中,只要有可能出现混淆的地方,都会显式使用this限定符。例如,在之前的赋值操作符中,有如下语句:

<code>this-&gt;_count = source._count;</code>

也可以写成:

<code>_count = source._count;  // 这样写也正确!</code>

但是,同一语句中,通过不同的对象多次用相同的名称_count会令人困惑。因此,要显式使用this限定符。

什么时候必须使用this指针?当我们希望返回对调用某函数的对象的引用时,必须使用*this。否则,如何显式表示“我的对象”这个概念?另一种情况是(如前所述的赋值操作符中),我们希望获得对象的地址,也必须显式使用this名称。到目前为止,这是显式使用this名称最常见的两种情况。

1一些编译器用n和f区别near和far函数,即用n代表near函数,用f代表far函数。

2译者注:arm指的是margaret a. ellis与bjarne stroustrup合著的书:annotated c++ reference manual。isbn 0-201-51459-1。

3尽管链接器(和开发环境)越来越智能,开发环境为用户显示未经重整的名称也越来越普遍。但是,粗略了解一下名称重整仍然有好处。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

继续阅读