this指针的本质是指针常量
认识this指针
#include <iostream>
using namespace std;
class Line {
private:
int m_length;
public:
Line(int len):m_length(len){};
void showLength(){cout << m_length << endl;}
//cout << this->m_length << endl;
};
int main() {
Line l1(10);
Line l2(20);
l1.showLength();
l2.showLength();
return 0;
}
在C++中成员变量和成员函数是分开存储的 ,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码,那么问题是:这一块代码是如何区分那个对象调用自己的呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象,this指针是隐含每一个非静态成员函数内的一种指针(包括构造函数和析构函数)。this指针不需要定义,直接使用即可。 即类的每个非静态成员函数都有一个this指针指向调用这个成员函数的对象。当一个对象调用成员函数时,编译系统先将对象首地址赋给this指针,然后调用成员函数。在成员函数存取数据成员时,隐含的使用了this指针,这样成员函数就能够通过this指针来访问目的对象的数据成员。
在上例中,当l1调用showLength()时,编译系统把对象l1的起始地赋给this指针。因此,在成员函数引用数据成员时,就按照this指向找到对象l1的数据成员。例如showLength()要输出m_length的值,实际上是执行以下语句:
cout << this->m_length << endl;
由于this指向l1,因此相当于执行以下语句:
cout << l1.m_length << endl;
成员函数定义如下:
void showLength(){cout << m_length << endl;}
C++编译器把它处理为:下述过程由编译系统自动实现,不必人为的在形参在增加this指针,也不必将对象的地址传给this指针。同时,在需要时也可以显式的使用this指针。
void showLength(){cout << this->m_length << endl;}
//隐式使用this指针
void showLength(){cout << m_length << endl;}
//显式使用this指针
void showLength(){cout << this->m_length << endl;}
return *this
在类的非静态成员函数中返回对象本身,可以使用return *this
链式编程思想
#include <iostream>
using namespace std;
class Line {
private:
int m_length;
public:
Line(int len): m_length(len) {};
void showLength(){cout << m_length << endl;}
Line& addLength(const Line &l);
};
Line& Line::addLength(const Line &l) {
m_length += l.m_length;
return *this;
}
int main() {
Line l1(10);
Line l2(20);
Line l3(50);
l1.addLength(l2).addLength(l3); //链式编程思想
cout << "10+20+30=";
l1.showLength();
return 0;
}
Line& addLength(const Line &l);
上述addLength()函数是将传入的对象的m_length值加到调用该函式的对象l1的m_length上。 由于我们返回的是该对象本身,所以在执行完l1.addLength(l2)后紧接着执行l1.addLength(l3),注意,在这里我们的函数返回值类型为引用,可以直接操作原数据。从而实现了可以在尾部直接添加的链式编程思想。其实cout也是一个链式编程思想的典型应用。
一定要注意,函数返回值类型为引用!如果我们的返回值类型不是Line& 而是Line,又会出现什么情况呢?
Line Line::addLength(const Line &l) {
m_length += l.m_length;
return *this;
}
因为函数返回值类型为Line,因此在执行完l1.addLength(l2)后l1.m_length为30,返回的是l1的拷贝l1a(暂且称为l1a), 接下来再执行时其实使用的是l1a,l1a.addLength(l3),现在你懂为什么函数返回值类应该是引用了 吧。