1.this指针的特性
1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用。
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。 所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用 户传递。
大家有没有想过一个问题--->this指针存在哪里呢?
之前说过this指针是一个形参,那么形参是存放在栈的,这里需要注意的是这个栈不是数据结构的栈,而是存储空间的栈,有时候this指针也会存在寄存器ecx中,因为ecx速度很快。
class A
{
public:
void Print()
{
cout << "Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
上述代码运行结果是什么呢?
A、编译报错 B、运行崩溃 C、正常运行
想必大家应该会选择B吧,因为这里出现了空指针的解引用,那么事实真的如此吗?
我们运行来看一下:
我们看到代码正常运行,那么为何会这样呢?
我们创建了类类型的指针,并且将其赋值为空指针,这里的空指针其实可以将其看为对象的地址,这里的空指针别没有解引用,因为我们去调用成员函数时,只是将对象的地址传给该函数,如果是指针,就将指针传过去。传递空指针并不会导致运行崩溃。
需要注意的是,如果当成员函数中需要使用到成员变量时,运行就会崩溃,这是因为this中保存的是空指针,再去访问成员变量就会出错。

2.构造函数
构造函数是默认成员函数的其中一个,所谓默认成员函数,就是你在创建类后,如果我们不显示写,编译器就自生成。功能其实就是帮助我们初始化。
2.1特性
构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开 空间创建对象,而是初始化对象。
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成 员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。
其特征如下:
1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
2.2创建构造函数
我们发现当我们没有去调用构造函数时,就会自动调用将其初始化,我们也可以选择去调用构造函数,调用方式为类型加对象()。
需要注意的是,如果我们在成员函数中,重载了构造函数,那么自动调用时,只会自动调用不需要传参的哪一个构造函数:
2.3自动生成的构造函数会做什么?
那么问题来了,当我们不写时,自动生成构造函数会帮我们完成初始化吗?
我们发现并没有将其初始化,因为打印出来全是随机值。
那么如果我们在成员变量中加入自定义类型会则么样呢?
class A{
public:
A() {
_i = 1;
_n = 2;
}
private:
int _i;
int _n;
};
class Date {
public:
void print() {
cout << _year << "_" << _month << "_" << _day << endl;
}
private:
int _year;
int _month;
int _day;
A _a;
};
int main() {
Date d1;
return 0;
}
我们通过调试来观察一下这里的_a是否会被初始化:
我们发现自动生成的构造函数,对内置类型的数据不管,对自定义类型的数据,调用该类的不需要传参的那个构造函数进行初始化。
注意:如果自定义类型没有写了需要传参的构造函数,没有写不需要传参的构造函数,那么就会报错没有合适的默认函数可用。
当然在成员变量没有自定义类型时也会报错:
