1. 类的基本概念
1.1 碎片知识
① 类的定义。
class className
{
// 类体:由成员函数和成员变量组成
};
其中,class为定义类的关键字,className为类的名字,{}中为类的主体。类中的元素称为类的成员,类中的数据称为类的属性或者成员变量;类中的函数称为类的方法或者成员函数。
② 类有三大访问限定符
- public(公有):它修饰的成员可以在类外直接进行访问
- protected(保护):它修饰的成员不可以在类外直接进行访问
- private(私有):它修饰的成员不可以在类外直接进行访问
a. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)。
b. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符现时为止。
c. class的默认访问权限为private,struct为public(因为struct要兼容C)。
面试题:
C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中的struct可以当成结构体去使用,并且C++中struct还可以用来定义类。和用class定义类是一样的,区别是struct的成员默认访问方式是public,而class的成员默认访问方式是private。
③ 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
④ 类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 ::
作用域解析符指明成员属于哪个类域。
⑤ 用类类型创建对象的过程,称为类的实例化
⑥
1.2 类大小的计算
类的大小的计算和结构体大小的计算是一样的,可以参考我之前写的面试必考:内存对齐(字节对齐)、位段(位域)的计算,以及枚举类型、联合体中的内存对齐小节。
一个类的大小只跟成员变量有关系,跟成员方法是没有关系的,成员方法是放在公共的代码区,该类实例化出的所有对象均可调用。
如图:
空类:就是指没有任何的成员变量,只有成员方法或直接什么都没有的类,计算机会默认给1Byte的大小来标识该类
2.this指针
2.1 概念
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
举个例子就是
class A
{
public:
void setData(int data);
};
void main()
{
A t; // 实例化一个对象
t.setData(&t,1);//相当于调用了setData(1);
}
其中,void setData(int data)
方法将隐藏的this指针展开来写就是void setData(A* const this,int data)
.即this指针了代表当前对象的地址。
2.2 特性
- this指针的类型:类类型* const(即
A* const this
) - this指针只能在成员函数的内部进行使用
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
当对象调用一个成员方法时,this指针会先识别类名,再识别成员变量,最后再识别方法并进行相应的改写。
那么问题来了,this指针存在哪里?
解答:this指针在成员方法的参数列表中,(因为方法没有在对象中保存,而是在一个公共的代码区中存放),因此,this指针位于栈区中,只有当对象调用时,才会生成。
3. const成员函数
首先对于一个指针而言,该指针能对应到的含义有两个:①该指针所指向的值、②该指针自身的值。那么const所封锁的范围就是这两个内容。
那么const所能出现的位置就有两个,指针之前和指针之后,指针之前封锁的就是该指针所指的值,指针之后封锁的就是该指针自身的值。所对应的情况就有:
const int * q
:指针 q 所指向的内容不允许修改。(const在指针之前)int const * q
:指针 q 所指向的内容不允许修改。(const在指针之前)int * const q
:指针 q 自身的内容不运行修改。(const在指针之后)int * q const
:指针 q 自身的内容不允许修改。(const在指针之后)const int * const q
:指针 q 自身的内容和 q 所指向的内容均不允许修改。
那么将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。即给成员函数加上const之后,就不可以修改成员变量的值,该成员函数也可被称为常方法。
即
int GetData() const
就等价于int GetData(const Test* const this)
,对this指针自身的值和指向的值都进行封锁,因此才不能对成员变量进行修改。
加const的方法和不加const的方法是可以构成重载的
假设Test类中有两个函数
int GetData()
和int GetData() const
两个函数,那么我们来对比一下它们在程序汇编的阶段后经过编译
器修饰后的函数名是否相同来判断它是否能够重载。
①int GetData()
②
int GetData() const
对比一下,会发现两者的函数名是不相同的,因此是可以构成重载的。
思考:
- const对象可以调用非const成员函数吗?
- 非const对象可以调用const成员函数吗?
- const成员函数内可以调用其它的非const成员函数吗?
- 非const成员函数内可以调用其它的const成员函数吗?
用一张图来解释即是如下图: