先说说类
类
类有两种定义方式:
1. 声明和定义全部放在类中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2. 声明放在.h文件中,类的定义放在.cpp文件中
类的访问和封装
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体去使用。另外C++中struct还可以用来定义类。 和class是定义类是一样的,区别是struct的成员默认访问方式是public,class是struct的成员默认访问方式 是private。
面向对象的三大特性:封装、继承、多态。
在类和对象阶段,我们只研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。 封装本质上是一种管理
类的实例化:
1. 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
3. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占 用物理空间
类对象模型
这里需要注意的是有两点比较重要
第一是计算类对象的大小
第二是类对象的存储方式
解决第一个问题,首先要清楚第二个问题:
一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类。
接下来计算大小就根据结构体内存对齐的规则来计算,这里可以回想一下C语言内容中提出的几个问题:
1. 结构体怎么对齐? 为什么要进行内存对齐
2. 如何让结构体按照指定的对齐参数进行对齐
3. 如何知道结构体中某个成员相对于结构体起始位置的偏移量
4. 什么是大小端?如何测试某台机器是大端还是小端,有没有遇到过要考虑大小端的场景
内存对齐:
C语言深度解析之六:自定义类型详解(结构体+枚举+联合)_何以过春秋的博客-CSDN博客
大小端:
C语言深度解析之一:数据存储_何以过春秋的博客-CSDN博客
this指针
说起this指针,其实就是从C++与C语言之间不同的语法特性出发的。
每一个对象都能通过 this 指针来访问自己的地址:this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。他的类型是* const
友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。
同时,静态成员函数也没有this指针。
为了引入this指针,我们看一个例子
class Date
{
public :
void Display ()
{
cout <<_year<< "-" <<_month << "-"<< _day <<endl;
}
//void SetDate(Date* this,int year , int month , int day)
void SetDate(int year , int month , int day)
{
_year = year;
//this->_year = year;
_month = month;
//this->_month = month;
_day = day;
//this->_day = day;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
int main()
{
Date d1;
Date d2;
d1.Init(2021,10,8);
//d1.Init(&d1,2021,10,8);
d2.Init(2022,10,8);
d1.Display();
d2.Display();
return 0;
}
Date类中有SetDate与Display两个成员函数,函数体中没有关于不同对象的区分,如果创建了d1,d2两个对象,那当d1调用SetDate函数时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?
所以这里实际上有一个this指针,它指向当前对象,通过它可以访问当前对象的所有成员。
我们在调用成员函数后,编译器其实会再传一个参数进去,这个参数为当前对象的地址:
d1.Init(&d1,2021,10,8);
而成员函数本质上是这样:
void SetDate(Date* this,int year , int month , int day)
{
this->_year = year;
this->_month = month;
this->_day = day;
}
解释完this指针后,来看下面这个程序:
class A
{
public:
void show()
{
cout<<"show()"<<endl;
}
void Print()
{
cout<<_a<<endl;
}
void PrintA()
{
cout<<"PrintA()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->show();
p->Print();
p->PrintA();
return 0;
}
三次调用函数这个程序的结果是什么?
第一行第三行正常运行,第二场直接崩溃
这里还引出了一个面试问答:this指针可以为空吗?
最后谈一个问题:this指针存在哪里?
不是存在对象中哦
this指针是形参,形参和函数中的局部变量都是存在函数栈帧里面的,所以this指针是存在栈区的,vs下this指针是通过寄存器ecx传递的