首页 > 代码库 > this指针和 *this

this指针和 *this

        我们都知道,类的成员函数有一个附加的隐形形参,即指向该类对象的this指针,它与调用成员函数的对象绑定在一起。那么,这个this指针究竟是什么样的指针呢?其解引用*this返回的又是怎样的一个对象呢?

首先,我们以《C++ Primer》书中的Screen类为例说明,这个类只是简单声明,有些成员函数的具体实现没有定义。不必关注成员函数的实现,只需要看它的形式即可。



//定义一个名为Screen的类型来表示计算机上的窗口
#include <iostream>
#include <string>
using namespace std;
class Screen
{
public:
	//使用类型别名来简化类
	typedef string::size_type index;
	//构造函数
	Screen(index hght,index wdth,const string &cntnts=""):
	height(hght),width(wdth),cursor(0),contents(cntnts){}
	//返回光标的位置
	index get_cursor() const{return cursor;};
	//增加三个成员函数,返回*this
	Screen& move(index r,index c);//给定两个index值,将光标移至新位置
	Screen& set(char);//将特定字符设置为特定值
	const Screen& display(ostream &os) const;//输出内容
private:
	std::string contents;//窗口内容
	index cursor;//光标当前停留的位置
	index height,width;//窗口的高度和宽度
};
//给定两个index值,将光标移至新位置
Screen& Screen::move(index r,index c)
{
	index row=r*width;
	cursor=row+c;
	return *this;
}
//将特定字符或光标指向的字符设置为特定值
Screen& Screen::set(char c)
{
	contents[cursor]=c;
	return *this;
}
//输出内容
const Screen& Screen::display(ostream &os) const
{
	os<<contents;
	return *this;
}
int main()
{
	//根据屏幕的高度、宽度和内容的值来创建Screen
	Screen myscreen(5,6,"abcde\nfghij\nklmno\pqrst\nuvwxy");
	myscreen.move(4,0).set('#').display(cout);
	cout<<endl;
	return 0;
}

基本概念

  1. const指针——指针本身的值不可修改,只能指向指定位置的对象
    其定义如下:
    int errNumb = 0;
    int *const curErr=&errNumb;//curErr是一个指向int型对象的const指针
    可以改变const指针所指向的值,但不能改变const指针所保存的地址,如下:
    *curErr=1;//curErr所指向的值变为1,即errNumb=1
    ++curErr;//错误,curErr是一个常量,不能改变
    const指针在定义时必须初始化,一经初始化,则指针本身不可再修改,只能指向初始化时的对象。
  2. 指向const对象的指针——只能读取对象,不能利用指针修改对象
    其定义如下:
    const double pi = 3.14;
    const double *cptr = &pi;//cptr是一个指向const对象pi的指针
  3. 常(const)成员函数
    在形参表后用const修饰的成员函数,表示只能读取类的数据成员,不能修改。如上例中的index get_cursor()const{return cursor;};
  4. 常(const)对象
    在定义类对象时用const修饰的对象,常对象只能调用类中的常成员函数,而普通的对象则没有此限制。如下例:
    const Screen herscreen();//herscreen就是一个Screen类型的常对象

this指针

  1. this指针是指向类类型的const指针
    调用成员函数时,隐藏的this指针被初始化为调用成员函数的对象的地址,可以改变this所指向的值,但不能改变this所保存的地址,即this指针只能指向该对象,不能指向别的对象。所以,无论在非const成员函数还是const成员函数中,this首先是一个指向类类型的const指针。在上例中,非const函数Screen& move(index r,index c)的this类型如下:
    Screen *const this
  2. const成员函数中的this指针——指向常(const)对象的const指针
    在普通的非const成员函数中,this的类型就是一个指向类类型的const指针。
    而在const成员函数中,因为不能通过this指针修改类的数据成员,只能读数据成员,故this的类型是一个指向常(const)类对象的const指针。既不能改变this所指向的对象,也不能改变this所保存的地址。在上例中,const成员函数 get_cursor() const的this的类型如下:
    const Screen *constthis

返回*this——返回的是一个对象的引用

  1. 何时返回*this
    当我们需要将一个对象作为整体引用而不是引用对象的一个成员是。最常见的情况就是在这样的函数中返回*this:
    该函数返回对调用该函数的对象的引用。
    如上例中的
    myscreen.move(4,0).set(‘#‘);
    等价于
    myscreen.move(4,0);
    myscreen.set(‘#‘);
  2. 返回的对象引用是什么类型:常对象引用 or not?
    在普通的非const成员函数中,*this返回的普通的对象引用。在上例中,非const成员函数move( )返回的就是一个普通的对象引用:
    <span style="color:#ff0000;">Screen&</span> move(index r,index c)
    {
    	index row=r*width;
    	cursor=row+c;
    	<span style="color:#ff0000;">return *this;</span>
    }


    而在const成员函数中,*this返回的是常(const)对象引用。在上例中,const成员函数display() const返回的就是一个常(const)对象的引用:
    <span style="color:#ff0000;">const Screen&</span> display(ostream &os) <span style="color:#ff0000;">const</span>
    {
    	os<<contents;
    	<span style="color:#ff0000;">return *this;</span>
    }
    注意:
    不能从const成员函数返回指向类对象的普通引用,而应该是const引用。const成员函数只能返回*this作为一个const引用。

    Screen&
     display(ostream &os) const; //错误,const成员函数返回的应该是一个const对象引用

    那么返回类型之间的区别又会导致什么结果呢?
    我们知道,常(const)对象只能调用const成员函数,而普通对象既能调用const成员函数,又能调用非const成员函数。所以,我们可以判断以下调用是否正确?
    mysceen.move(4,0).set(‘#‘); //正确,因为非const成员函数move()返回的是普通引用,可以调用一切成员函数
    myscreen.move(4,0).display(cout);//正确
    myscreen.display(cout).set(‘#‘); //错误,因为const成员函数display()返回的常对象引用,只能调用const成员函数,而set.()是非const成员函数

    因此,我们可以确定,返回类型的不同对调用成员函数有了限制。
现在,我们可以做出结论了:
  1. 非const成员函数的this是一个指向类类型的const指针,可以改变this所指向的值,但不能改变this所保存的地址,即不能再指向别的对象。
    const成员函数的this是一个指向常(const)类对象的const指针,既不能改变this所指向的对象的值,也不能改变this所保存的地址。

  2. 非const成员函数的*this返回的是普通引用,可以调用一切成员函数。
    const成员函数的*this返回的是常(const)对象引用,只能调用const成员函数。
上面只是我学习过程中的一些浅显理解,拿出来与大家共享,也希望得到大家的指点。

this指针和 *this