this指针概念
- 概念引出
-
c++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inline member function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码,c++通过提供特殊的对象指针(this指针)区分调用的对象,this指针指向被调用的成员函数所属的对象。
- this指针概念
-
c++规定,this指针是隐含在对象成员函数内(实际存放于形参中)的一种指针
-
当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。
-
因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。
-
this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。
- this指针本质:当一个对象调用某成员函数时编译器会隐式传入一个参数, 这个参数就是this指针
-
this指针中存放的就是这个对象的首地址。
-
其实编译器在生成程序时加入了获取对象首地址的相关代码,并把获取的首地址存放在了寄存器ECX中(VC++编译器是放在ECX中,其它编译器有可能不同)。
-
成员函数的其它参数正常都是存放在栈中,而this指针参数则是存放在寄存器中。
- this指针永远指向当前对象
-
成员函数通过this指针即可知道操作的是那个对象的数据。
-
This指针是一种隐含指针,它隐含于每个类的非静态成员函数中。
-
This指针无需定义,直接使用即可。
- 静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。
-
类的静态成员函数因为没有this指针这个参数,所以类的静态成员函数也就无法调用类的非静态成员变量。
this指针工作原理
类中定义的非静态成员函数,编译器会隐式的添加一个形参this,在调用非静态成员函数时编译器会对this传递当前对象的地址,所以在函数中就可以使用this指代当前对象
this指针的使用
-
当形参和成员变量同名时为避免命名冲突,可用this指针来区分
当两个名字相同的变量,其中一个有确切的来源(非本对象)时,另一个未标注来源的同名成员变量,或只有一个成员变量时,编译器会隐式的为其添加this指针 -
在类的非静态成员函数中可使用return *this返回对象本身(链式编程)
this是指向对象的指针(*this)则是对象本身,函数中使用return返回(*this)即返回该对象本身,可以继续调用该对象方法或成员属性
注意,当以值的方式(函数返回对象类型而不是对象引用类型)时,将会触发拷贝构造,函数将会返回一个重新开辟的对象,该对象与返回的对象成员相同
空指针访问成员函数
类中定义的非静态成员函数,编译器会隐式的添加一个形参this,在调用非静态成员函数时编译器会对this传递当前对象的地址,所以在函数中就可以使用this指代当前对象
当声明一个为空(NULL)的对象指针,虽然该指针没有指向任何空间,但是编译器还是会为其添加this指针,只是该this指针也为空,当使用该空指针调用成员函数时,若函数中并没有使用到this指针(没有用到对象成员属性和this指针),该函数调用将可以实现
常函数与常对象(const修饰的函数与对象)
- mutable关键字
- mutalbe的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。
- 在C++中,mutable也是为了突破const的限制而设置的,被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
- 当成员变量类型符前用mutable修饰时,成员属性在常函数中将可以进行修改操作
- 常函数( const修饰成员函数)
- 当使用const修饰的成员函数时,const关键字会修饰函数中this指针指向的内存区域,此时成员函数体内将不可以修改本类中的任何普通成员变量
- this在函数中是无法改变的,他被声明为const类型,如Person * const this;,但虽然this无法修改(即对象无法被修改)对象的属性还是可以被修改,所以还需要使用const修饰this将其指向的成员也无法被修改
-
语法:将const关键字放置在函数定义形参的()后函数体{}前即可
- 常对象(const修饰对象)
- 声明时使用const关键字修饰的对象被称为常对象
- 被const修饰的对象(常对象)将无法修改其内部未被mutable修饰的成员属性,且无法调用非const函数(常函数)(不确定函数中是否对属性进行修改)
- 常对象只能调用const的成员函数
- 常对象可访问 const 或非 const 数据成员,而不能对数据成员进行修改,除非成员用mutable修饰