----------------siwuxie095
this 指针
看如下实例:
定义一个 Array 类,数据成员为:len
通过观察,可以发现:参数和数据成员并不同名
看如下实例:
如果同名,有如下问题:
构造函数中,如果这样写,不管是人类还是计算机,都无法判断究竟是
将参数赋值给数据成员了,还是将数据成员赋值给参数了
setLen() 函数中同理 …
既然计算机无法判断,就会把这样的赋值认为是错误的
可见:主要问题在于编译器无法分辨哪个是作为参数的 len,
哪个是作为数据成员的 len
这就是说,迫切的需要一种技术,这种技术要么可以标记出
参数,要么可以标记出数据成员,这种技术正是 this 指针
this 指针,即 指向对象自身数据的指针
如果使用 Array 类实例化一个对象 arr1,this 指针就相当于是给 arr1 取地址,
即 this 是 arr1 的地址,如果再实例化一个对象 arr2,那么 this 指针此时就是
arr2 的地址
在内存空间中的表示:
this 如果写在 arr1 中,就是 arr1 的地址,如果写在 arr2 中,就是 arr2 的地址
可见:this 要表达什么意思取决于它放在什么位置,通过 this 指针可以访问到它
表达的对象自身的任何数据
从另一个角度来说,就可以标记出它自身的数据成员,应用到
代码中就可以写成这样:
「参数和数据成员同名时,计算机就不会再疑惑,也能够正常的编译通过」
继续观察之前的例子,难道大家没有对成员函数中直接去访问数据成员
这种做法产生过怀疑吗?
回顾对象结构的实例:
car1、car2、car3 都有自己的数据成员,但成员函数却只有一份,
这份成员函数写在代码区,三个对象都可以各自访问代码区中的成
员函数,而且访问时也不会出任何的问题,在成员函数被调用的时
候,也各自调用到了每一个对象的数据成员,并且没有出现混乱
那么问题来了:既然函数的逻辑代码都是以二进制的形式存储在代
码区,参数中也没有数据成员,那么在调用数据成员,尤其是存在
多个对象时,函数如何确定该调用哪个对象的数据成员呢?
要解决这个问题,也归功于 this 指针,看如下实例:
不难发现,每一个成员函数的参数列表中都多出了一个 this 指针,而
有了这样一个 this 指针,前面的问题也就迎刃而解了
我们可以设想一下,当实例化对象并使用这些成员函数时,this 指针
就代表着这个对象本身的地址
当实例化 arr1 时,构造函数中传入参数 this,当执行给 len 赋值
10 的操作时,相当于是在执行 this 的 len 赋值 10 的操作,因为
this 就指的是 arr1,所以用 this 指向 len 时,其实指向的是 arr1
的 len,也就不会给其他的对象赋错值了
同理,如果用 arr1 调用 getLen() 时,也传入了参数 this,当调用
return len 时,相当于调用 return this->len,也就是 arr1 的 len
当实例化 arr2 时,此时的 this 就已经是 arr2 的地址了 …
从而使 arr1 和 arr2 在同时调用这些成员函数时,不会产生对象错
乱的情况
因为每次调用成员函数,都需要 this 指针,所以 C++ 的编译器
干脆就替我们干了这件事,于是摆在我们面前的成员函数就成了
现在的样子:不加 this
其实在编译时,编译器自动的为每一个成员函数的参数列表都加了
一个 this 指针
因为编译器为我们干了这些事情,所以自定义时就不必要再加 this
指针这个参数,使用的时候也完全可以当做没这回事儿
程序 1:
Array.h:
class Array { public: Array(int len); ~Array(); void setLen(int len); int getLen(); void printInfo(); private: int len; }; |
Array.cpp:
#include "Array.h"
Array::Array(int len) { //容易混淆的地方用this指针标记(不标记的话编译器就不知道 //是参数给数据成员赋值还是数据成员给参数赋值) this->len = len; }
Array::~Array() {
}
void Array::setLen(int len) { this->len = len; }
int Array::getLen() { return len; }
void Array::printInfo() {
} |
main.cpp:
#include <stdlib.h> #include "Array.h" #include <iostream> using namespace std;
int main(void) { Array arr1(5); cout << arr1.getLen() << endl; system("pause"); return 0; } |
程序 2:
Array.h:
class Array { public: Array(int len); ~Array(); Array* setLen(int len); int getLen(); Array& printInfo(); private: int len; }; |
Array.cpp:
#include "Array.h" #include <iostream> using namespace std;
Array::Array(int len) { //在容易混淆的地方用this指针标记 this->len = len; }
Array::~Array() {
}
Array* Array::setLen(int len) { this->len = len; //return出去的是arr1的this指针 return this; }
int Array::getLen() { return len; }
Array& Array::printInfo() {
cout << "len=" << len << endl; return *this;//return出去的是arr1的引用 }
//Array Array::printInfo() //{ // // cout << "len=" << len << endl; // return *this;//return出去的是新的临时对象 //} |
main.cpp:
#include <stdlib.h> #include "Array.h" using namespace std;
//this 指针的本质就是其所在对象的地址 int main(void) { Array arr1(10); //根据返回值类型的不同选择不同的操作符 . 和 -> arr1.printInfo().setLen(5)->printInfo(); system("pause"); return 0; }
//printInfo() 前面是Array& 当setLen(5)时 // //arr1.printInfo().setLen(5); //arr1.printInfo(); // //最终打印出一个10 一个5
//如果printInfo()前面不是Array& 而是Array //那么return出来的就是一个新的临时对象(是另外的对象,并不是arr1) //当setLen(5)时 // //arr1.printInfo().setLen(5); //arr1.printInfo(); // //就会打印出两个10 而不是一个10 一个5
//Array& 和 Array* 效果一样只不过一个是指针一个是引用罢了 //这便是Array Array& Array* 的不同与妙用了
//假如我在printInfo()函数中把原来的cout换成 cout<<this<<endl; //即打印出this指针的地址同时在main()函数中 cout<<&arr1<<endl; //这样就可以清晰的看到this指针指向的是对象的地址(this指针的本质) |
【made by siwuxie095】