C++类与this指针
1.类
1.1.什么是类?
class Name
{
// 类体:由成员函数和成员变量组成
};
上述代码中:class为定义类的关键字,Name为类的名字,{}中为类的主体,注意:类定义结束时后面分号。
类中的元素称为类的成员;类中的数据称为类的属性或成员变量;类中的函数称为类的方法或成员函数。
类的两种定义方式:
1. 声明和定义全部放在类体中。注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2.声明放在.h文件中,类的定义放在.cpp文件中 。
注:在一般情况下,更期望使用第二种方式
1.2.访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符说明:
1. public修饰的成员在类外可以直接被访问;
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的);
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止;
4. class的默认访问权限为private,struct为public(因为struct要兼容C)。
【面试题】
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。和class是定义类是一样的,区别是struct的成员默认访问方式是public,class中是struct的成员默认访问方式是private。
1.3.封装
什么是封装?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理:我们使用类数据和方法都封装到一下。不想被别人看到的,我们使用protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访问。所以封装本质是一种管理。
【面试题】
面向对象的三大特性:封装、继承、多态。
2.this指针
2.1.什么是this指针?
我们首先来定义一个日期类Date:
class Date
{
public:
void Display()
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
void SetDate(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
// 建议成员变量加"_"
int _year; // 年
int _month; // 月
int _day; // 日
};
int main()
{
Date d1, d2;
d1.SetDate(2020, 4, 1);
d2.SetDate(2020, 4, 2);
d1.Display();
d2.Display();
return 0;
} // 日期类
问:Date类中有SetDate与Display两个成员函数,函数体中没有关于不同对象的区分,但是当s1调用SetDate函数时,函数是怎样知道应该设置s1对象,而不是设置s2对象呢?
答:在C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户都是透明的,即用户不需要来传递,编译器自动完成。
2.2.this指针的特性
1. this指针的类型:类类型 *const
2. 只能在成员函数的内部使用
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
【面试题】
1. this指针存在哪里?
A.栈 B.堆 C.数据段 D.代码段 E.对象中
答:A,this指针是隐含的形参(但是在一些地方也会存在寄存器中,在VS下通过寄存器ecx传递,来提高效率)。
2. this指针可以为空吗?
可以为空,当我们在调用函数的时候,如果函数内部并不需要使用this,也就是不需要通过this指向当前对象并对其进行操作时可以为空(定义一个空函数或在里面随便打印一个字符串),如果调用的函数需要指向当前对象,并进行操作,则会发生错误(空指针引用)就跟C中一样不能进行空指针的引用。(下题对此问题进行了解答)
3.请看下面程序,程序能编译通过吗?
下面程序会崩溃吗?在哪里崩溃?
class A
{
public:
void PrintA()
{
cout << _a << endl;
}
void Show()
{
cout << "Show()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA(); // 崩溃
p->Show(); // 正常运行
// 因为p->Show()没有对this指针进行解引用
}
答:程序不能通过,会在调用p->PrintA()函数并进行访问成员变量时,函数会崩溃。
解析:p是一个空指针,只有在空指针解引用时会崩溃。在函数 p->PrintA()中,this是一个空指针,当它访问成员变量_a时,会进行解引用,所以程序会崩溃;而在函数p->Show()中,由于函数都存在公共代码段,不在对象中,所以this没有指针进行解引用,程序正常运行。