先看段代码
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" <<_month << "-" <<_day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
d1.Init(2022, 7, 5);
d2.Init(2022, 7, 6);
d1.Print();//输出2022-7-5
d2.Print();//输出2022-7-6
return 0;
}
然后是下面这段代码。其实这两段代码除了cout<<this<<endl;都是一样的
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << this << endl;
cout << this->_year << "-" <<this-> _month << "-" <<this-> _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2;
d1.Init(2022, 7, 5);
d2.Init(2022, 7, 6);
d1.Print();//输出00000001000FF768和2022-7-5
d2.Print();//输出00000001000FF798和2022-7-6
return 0;
}
这个this是什么东西呢?其实它是隐形的在函数参数里面的,在上面这段代码就是
void Print(Data*const this)
但是不能写出来的让它显性出现的,不然会报错。显然它是一个形参,那么和一般的形参一样,this指针存在函数调用的栈帧里面。来看下面这段代码
#include<iostream>
using namespace std;
class A {
public:
void Print() {
cout << "Print()" << endl;
}
private:
int _a;
};
int main() {
A* p = nullptr;
p->Print();//输出Print()
return 0;
}
上图说明空指针传参给this是可以的。这个函数的地址不在对象中,p会作为实参传给this指针
#include<iostream>
using namespace std;
class A {
public:
void Print() {
cout <<_a<< endl;
}
private:
int _a=1;
};
int main() {
A* p = nullptr;
p->Print();//报错。这里并没有实例化对象,因此没有成员变量_a,不能调用
return 0;
}
还有最后一段代码
#include<iostream>
using namespace std;
class A {
public:
void Print() {
cout << "Print()" << endl;
}
private:
int _a;
};
int main() {
p->Print(nullptr);//报错。之前说过this指针不能显性出现,或者显性传参
return 0;
}
最后补充个额外知识,如果没有初始化成员变量直接使用会怎么样呢?
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Print();//输出-858993460,-858993460,--858993460
return 0;
}
这样会输出乱七八糟的东西,因此要向下面学习
#include<iostream>
using namespace std;
class Date
{
public:
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
// 内置类型
// C++11支持,这里不是初始化,因为这里只是声明
// 这里给的是默认的缺省值,给编译器生成默认构造函数用
int _year = 2;
int _month = 2;
int _day = 2;
};
int main()
{
// 构造函数的调用跟普通函数也不一样
Date d1;
//Date d1(); // 不可以这样写,会跟函数声明有点冲突,编译器不好识别
d1.Print();//输出2-2-2
return 0;
}
静态成员函数没有this指针,只有非静态成员函数才有,且为隐藏指针
非静态成员函数的第一个参数就是隐藏的this指针
this指针在非静态的成员函数里面,对象不存在
单纯的对this赋空是不可以的,不过可以强转直接赋空,不过一般不进行这样的操作
总结:
this指针需要注意的几点:
this 是 const 指针,它的值是不能被修改的,一切企图修改该指针的操作,如赋值、递增、递减等都是不允许的。
this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的。
只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用
this的本质:
this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。不过 this 这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器默默地将它添加到参数列表中。
this 作为隐式形参,本质上是成员函数的局部变量,所以只能用在成员函数的内部,并且只有在通过对象调用成员函数时才给 this 赋值。
成员函数最终被编译成与对象无关的普通函数,除了成员变量,会丢失所有信息,所以编译时要在成员函数中添加一个额外的参数,把当前对象的首地址传入,以此来关联成员函数和成员变量。这个额外的参数,实际上就是 this,它是成员函数和成员变量关联的桥梁。