类的引入
在C语言中,结构体是一种自定义数据类型,可以将不同的变量囊括在一起,提高了程序的可读性并且提升了CPU对内存的访问速度。
但是结构体也有一些不便利之处例如:只能包含不同类型的变量,在使用的时候 结构体名称需要和struct一起使用等等。
在C++中提出了一个类的概念。c++不仅兼容了C语言struct的所有用法,同时,struct 也升级为类。
在类中,不仅可以定义变量也可以定义函数。
c++对于结构体更多使用class关键字,当然struct也可以正常使用,但是二者在使用方法等方面略微有点区别。(后文会提到具体区别之处)
类的特点
1.类名就是类型。
2.类中可以定义函数
类的定义
那么类到底是如何定义的呢?我们到底要如何使用?
如图:
class 为类的关键字 :classname 类的名字
{} 中是类的主体 :还有结尾的分号不要忘记
类的主体:类的主体(类体)中的内容称为类的成员。类中的变量称为类的属性或成员变量。类中的函数称为类的方法或成员函数。
class sss
{
int _year; //成员变量
int _month;
int _day;
double time;
void Print() //成员函数
{
cout << _year<<endl;
cout << _month << endl;
cout << _day << endl;
}
};
类的访问限定符以及封装
前文我们提到,类可以使用class关键字。那么在使用类的时候方式与struct相同吗?
下面我们要了解到类的访问限定符
访问限定符
与C语言中 与结构体中 变量的使用 只需要 点操作符就可以随意使用 不同;类的成员的使用是有访问权限的。
因为c++实现封装的方式是:用类将对象的属性和方法结合到一块,让对象更加完善,通过访问权限 选择性的将其接口提供给外部的用户使用。
访问的权限就是由访问限定符来划分的。
访问限定符有三个 :public(公用)、protected(保护)、private(私有)
三者的区别在于:
1.public 修饰的成员在类里和类外都是可以随意访问的。
2.protected 和private 修饰的成员都只能在类里访问。类外不可以访问。
访问限定符有限定的范围:从此限定符开始到下一个限定符之间,或者到类的结尾(此限定符后面没有其他限定符)
访问限定符只在编译时有效,当数据映射到内存上时,没有任何访问限定符上的区别。
那么,struct 和class 的区别到底是啥呢?(在c++中)
在不写任何访问限定符的情况下
struct:成员默认公有(要兼容C语言)
class: 成员默认私有
类中函数的声明与定义
类中函数的声明方式有两种:
1.声明与定义全部放在类体中。但是此时编译器可能会将成员函数当做内联函数。
2.声明放在.h 文件中,成员函数定义放在 .cpp文件中。但是此时 成员函数名签需要加 类名::
因此,对于类中函数的声明与定义
建议:长的函数声明与定义分离。
短的函数,在类中统一声明与定义。
类的作用域
上文,函数的声明与定义分离时,在类外定义函数需要加 类名:: 这里涉及到了类的作用域的问题。
作用域:在c++中 {} 定义的都是域
类定义了一个新的作用域。类中所有的成员都在都在类的作用域中,在类体外定义成员时,都需要使用 :: 作用域操作符指明成员属于哪个类域。
类的实例化
概念
用类创建对象的过程称为类的实例化。
类与对象的关系:
类是对对象进行表述的,类似于一个模型一样的东西。模型限定了类有那些成员,定义出一个类,但是并没有分配实际的内存空间进行存储。
例如,开学的统计个人信息的信息表,表格可以看做是一个类。具体的某个学生的信息就是对象。
一个类可以十里出多个对象。实例化出的对象,会占用实际的物理空间,来存储类成员变量。
*(类是没有空间的,只有类实例化出的对象才有)
那么如何计算类对象的大小呢?
我们首先要清楚,类对象是如何存储的。
c++规定,类对象的存储方式是只存成员变量,不存成员函数。因为虽然每个对象的成员变量不同,但是它们用的函数都是一个,因此,类对象在存储的时候只保存成员变量,成员函数存放在公共代码段。
类对象大小的计算
计算类的大小时,计算的是成员变量的和。
空类,和没有成员变量大小的类,类对象大小都为1字节。
在计算成员变量的大小时,遵循内存对齐规则。
类成员函数的this指针
我们首先来看一段代码。
class name1
{
public:
void Init(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void Printf()
{
cout << _year << _month << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
name1 ss1;
name1 ss2;
ss1.Init(2023, 11, 26);
ss2.Init(2022, 10, 25);
ss1.Printf();
ss2.Printf();
return 0;
}
图中可以观察,两次调用的printf打印出来的是不一样的结果。
但是在前文中,我们提出,类中的成员函数使用的是同一个,并且在调用的时候也没有穿变量,那么Printf函数时如何辨别打印的内容的呢?
是因为this指针。
c++编译器给每个非静态的成员函数增加了一个隐藏的函数指针参数。让该指针去指向当前对象。咋函数体中,所以成员变量的操作都是通过该指针去访问。这种操作对用户是透明的,不需要用户来传递,编译器自动完成。
this指针的特性
1.this指针的类型 :类类型 *const,即,在成员函数中不可以给this指针赋值
2.只能在成员函数内部使用
3.this指针在本质上时成员函数的形参,对象中不存储this指针
4.this指针不需要用户进行操作,由编译器进行。
5.this指针实际上是个形参,是存在栈帧上面的