目录
前言:C++为什么要引入类这个概念?类是什么东西?类是怎么实现的?类有什么用?下面我们就类是怎么引入的来初步学习一下类
一、类的引入
C中的结构体中不允许有函数存在,只能定义变量,针对于这一点C++对其进行了拓展,C++的结构体不仅可以定义变量,还可以定义函数。
struct Student
{
void SetStudentInfo(const char* name, const char* gender, int age)
{
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintStudentInfo()
{
cout<<_name<<" "<<_gender<<" "<<_age<<endl;
}
char _name[20];
char _gender[3];
int _age;
};
上述代码C++中结构体定义会用class代替
二、类的定义
class className
{
// 类体:由成员函数和成员变量组成
};
class N1 {
char a; // 成员变量 (成员属性或数据成员)
int b;
long c;
void fun() { //成员方法
}
};
❤类的两种定义方式
1.声明和定义全部放在类体中
需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
class student {
void fun() {
}
char a;
};
2.声明放在.h文件中,类的定义放在.cpp文件中
//声明放在student.h文件
class student {
void fun();
char a;
};
//定义放在类的实现文件student.cpp中
#include"student.h"
void student::fun() { //这里用到了类的作用域
}
一般情况下,我们会选择第二种方式。
三、访问限定符及封装
在C++中,我们的对象可以包含变量和函数,将两者放到类中统一管理起来,这就是我们所说的对数据和数据操作的封装。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

四、类的实例化

(别问为什么用绿茶举例,因为喜欢喝😙)
五、类对象大小
class A1 {
public:
void f1() {}
private:
int _a;
};
// 类中仅有成员函数
class A2 {
public:
void f2() {}
};
// 类中什么都没有---空类
class A3
{};
void main() {
cout << sizeof(A1) << " " << sizeof(A2) << " " << sizeof(A3) << endl;
}
A1的大小为成员-a的大小,对比A2和A3,不能难发现类的成员函数并未占用类的空间,类仅是给成员属性分配了空间。
之所以A2和A3都是1,是因为我们定义了类,说明它有存在的意义,即使是空类,我们也要让它存在,但是它所含的内容为空,为了让编译器不会抹除掉它,编译器给他分配了数值,但这个数值不是随便给的,如果给大了,不但会造成空间浪费,还会对其他类不公平,所以给了它一个最小值来标记它。
那为什么类中的成员函数为什么没有空间呢?
我们再进行类的实例化时,可能会生成很多个对象,它们只是成员属性不同,对它们进行操作时,都会调用相同的相同的成员方法,每个对象保存私有成员方法的话会有些浪费空间。
1.什么是字节对齐?
在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为结构的每个成员按其自然边界(alignment)分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
为了使CPU能够对变量进行快速的访问,变量的起始地址应该具有某些特性,即所谓的”对齐”.
比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除.
数据的存储存储方式如下图:
❤结构体内存对齐规则
六、this指针
前文我们知道了对象并不会存储其所属类的成员方法,那我们在对对象进行操作时,成员方法是怎么认识我们怎么操作的那个对象的成员属性呢?
1.this定义
事实上C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
2.this特性

上图定义的形参为year,假如我们将其定义为_year,编译器会把它识别为成员变量,因此我们要避免类似情况发生 。
给个三连支持一下俺吧😊