首页 > 编程笔记 > C++笔记 阅读:503

C++ this指针详解

默认情况下,编译器为类的每个成员函数提供了一个隐式形参,该形参指向被调用的成员函数所在的对象。该隐式形参称为 this

先来看一个 Example 类的代码:
class Example
{
    int x;
    public:
        Example(int a){ x = a;}
        void setValue(int);
        int getValue();
}
再来看其成员函数的代码:
int Example::getValue()
{
    return x;
}
该成员函数的作用只是返回类对象中的值。以下就是 getValue 函数在程序中可能被调用的示例:
int main()
{
    Example ob1 (10), ob2 (20);
    cout << ob1.getValue() << " " << ob2.getValue();
    return 0;
}
在该示例中,程序将打印输出值 10 20

前面讲过,结构或类的不同对象称为该类的实例,并且类的每个实例都有自己的类数据成员副本。这些数据成员称为实例成员,因为它们属于类的实例。它们在不同的对象中可以具有不同的值。因此,在前面的示例中,ob1 对象中的实例成员 x 的值为 10,而 ob2 中的 x 的值为 20。

现在再来看一下该成员函数的代码:
int Example::getValue()
{
    return x;
}
该函数应该返回 Example 类的某个对象的 x 成员,但是它如何知道要使用哪个对象呢?这里会发生的情况就是:默认情况下,编译器为每个类的每个成员函数提供了一个隐式形参,该形参是指向类对象的指针。因此,如上例所示,getValue 函数配备了一个形参类型的指向 Example 的指针。

同样地,来看以下成员函数:
void Example::setValue(int a)
{
    x = a;
}
虽然程序员在编写时只釆用了一个 int 类型的形参,但实际上它有两个形参,其中一个就是指向 Example 类的对象的指针,另外一个自然是由程序员指定的以下形参:

int a

在所有这些情况下,隐式对象形参的实际形参就是调用成员函数的对象的地址。因此在以下调用中:

ob1.getValue()

传递给 getValue 函数的隐式形参是 ob1 的地址,而在以下调用中:

ob2.setValue(78)

传递给 setValue 的隐式形参是 &ob2。

编译器传递给成员函数的隐式指针可以由该函数内的代码通过使用保留关键字 this 来访问。因此,在以上示例中,Example 类的成员函数也可以通过使用以下表达式来访问调用它的对象:

*this

此外,也可以通过同一个指针访问该对象的任何成员。下面的程序说明了这些概念。它修改了 Example 类以包含一个成员函数,它使用 this 指针来打印调用它的对象的地址,以及在同一个对象中的实例成员 x 的值。
//ThisExample.h 的内容
class Example
{
    int x;
    public:
        Example(int a){ x = a; }
        void setValue(int);
        void printAddressAndValue();
};

//ThisExample.cpp 的内容
#include "ThisExample.h
#include <iostream>
using namespace std;
void Example::setValue(int a)
{
    x = a;
}
void Example::printAddressAndValue()
{
    cout << "The object at address " << this << " has " << "value " << (*this).x << endl;
}

//main程序的内容
//This program illustrates the this pointer.
#include <iostream>
#include "ThisExample.h"
using namespace std;

int main()
{
    Example ob1 (10), ob2 (20);
    // Print the addresses of the two objects
    cout << "Addresses of objects are " << &ob1 << " and " << &ob2 << endl;
    // Print the addresses and values from within the member function
    ob1.printAddressAndValue();
    ob2.printAddressAndValue();
    return 0;
}
输出结果为:

Addresses of objects are 0x241ff5c and 0x2411ff58
The object at address 0x241ff5c has value 10
The object at address 0x2411ff58 has value 20

现在来看一看以下成员函数,它是 this 指针的常见用法示例:
void Example::setValue(int a)
{
    x = a;
}
可以看到,该函数很自然地命名了一个形参 a,用来设置成员 x 的值。其实这个形参 a 可以改成一个更加直白的标识符,使它和成员 x 的意思连接更明显,例如,可以使用 xValue 之类的,甚至可以使用 x 本身。

但是,一个成员函数的形参如果与类的成员具有相同的标识符,则会导致类成员被隐藏,使得它在函数内部不可访问。因此,可以使用 this 指针来限定类成员的名字,以使其再次可见。以下就是按这种方式重写的 setValue 成员函数:
void Example::setValue(int x)
{
    this->x = x;
}

前面讲过,this->x 等价于 (*this).x。