【C++】隐含的“This指针“
目录
一、问题引入
二、定义
三、this 指针的特性
一、问题引入
我之前有一处疑惑,如果在成员函数中调用其他成员函数,如果不使用对象名作为前缀怎么判断的是要对哪个对象进行操作呢(虽然大概率是当前对象)?原来,成函数调用时会有一个隐藏的指针变量也就是this指针,它指向当前对象的位置,在调用该对象的成员函数时,其中的调用的其他的成员函数之前会自动加上这个指针,也就代表着当前对象的调用,如下:
#include <iostream>
//这是一个简单的日期类
class Date {
private:
int day;
int month;
int year;
public:
// 初始化方法
void Init(int d, int m, int y) {
day = d;
month = m;
year = y;
}
// 打印日期方法
void Print() const {
std::cout << day << "-"
<< month << "-"
<< year << std::endl;
}
// 自定义方法
void test(){
Print();//注意这里,我们可以直接使用Print()
//而不是像main函数一样在调用时需要再前声明类域
}
};
等价于以下操作:
void test()
{
this->Print();
}
二、定义
C++中的this指针是一个指向当前对象的指针。在类的成员函数中,可以使用this指针来访问当前对象的成员变量和成员函数。this指针的使用可以简化代码,提高代码的可读性和可维护性,这点如果你学过Python的话可以类比Python中的self指针的调用,Python中的调用是显式的,C++中是隐藏起来的。但是实际中,调用函数会自动携带它,会隐藏起来,但是仍能够使用,比如
void setAge(int a) {
this->age = a; // 使用this指针访问age成员变量
}
同样的,直接调用age也是可以的,不必须写入。
我们可以通过以下代码验证this指针实质是一个指向对象首地址的指针:
//在类中添加以下函数
void VerifyThisPointer() const
{
std::cout << "this指针的地址: " << this << std::endl;
}
//在main函数中调用
mian(void)
{
Date date(13, 11, 2024);
// 获取对象的地址
Date* datePtr = &date;
// 打印对象的地址
std::cout << "对象date的首地址: " << datePtr << std::endl;
// 调用 VerifyThisPointer 方法来打印 this 指针的值
date.VerifyThisPointer();
}
三、this 指针的特性
1. this指针的类型:"类"类型 * const (对应类的const指针型) ,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用。
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。可以通过观察汇编部分看出。而且就算是对象是一个空,也同样可以调用一部分成员函数。例如:
5.this在实参和形参位置不能显式得写出来,但是可以在类里面显式地用。如下:
#include <iostream>
//这是一个简单的日期类
class Date {
private:
int day;
int month;
int year;
public:
// 初始化方法
void Init(int d, int m, int y) {
this->day = d;
this->month = m;
this->year = y;
}
// 打印日期方法
void Print() const {
std::cout << this->day << "-"
<< this->month << "-"
<< this->year << std::endl;
}
// 自定义方法
void test(){
this->Print();
}
};
但是不可以这样使用:这样编译器会报错
void Init(Data* this, int d, int m, int y) {
this->day = d;
this->month = m;
this->year = y;
}
6.this指针不占用空间。前面我们已经知道this指针本质是对象的首地址,这个传递操作还是由编译器操作,它没有在对象内部,所以它不占用空间。
7.静态的成员函数没办法操作this指针。因为静态函数先于对象存在,例如即使没有对象的生成你也可以直接调用一部分静态函数。
第四点和第七点可以运行观察以下代码现象:
class Myclass
{
public:
static void staticPrint()//static修饰的静态成员函数
{
std::cout << "staticPrint()" << std::endl;
}
void Print()//非静态成员函数
{
std::cout << "Print()" << std::endl;
}
private:
int a;
};
int main(void)
{
Myclass::staticPrint(); //这样调用成功
Myclass::Print(); //这样会报错
Myclass* p = nullptr;
p->staticPrint(); //这样可以调用成功
p->Print(); //这样可以调用成功
return 0;
}