类的定义
c++struct:可以定义数据和函数,一般使用class。
c++定义类的方式
struct Student
{
void display()
{
}
void setId(int id)
{
_id = id
}
char name[10];
int _id;
};
class Student
{//成员函数
public://共有成员在任何地方可用
void display()
{
}
void setId(int id)
{
_id = id
}
private://私有的成员在类外不可见
//成员变量,属性
char name[10];
int _id;
protected://保护的成员在类外不可见
char major[10];
};
-
struct+()+ “;”
-
class+()+ “;”
c++的封装的语法体系:类,访问限定符
类的限定符以及封装
访问限定符:private; public; protected
- private:私有的成员在类外不可见;
- public:公有的成员在类外可见;
- protected:保护的成员在类外不可见。(作用范围是当前限定符开始到下一个限定符)
只限制成员在类外的访问权限,类内部不受访问限定符限制。
- class定义的成员默认访问权限为private。
- struct定义的成员默认访问权限为public。
类的作用域:类定义了一个新的作用域,所有类的成员都在类的作用域中,所有类成员都属于类域 。在类体外定义成员,需要使用::作为域解析符,指明成员属于哪个类域。
面向对象的三大特性
封装、继承、多态。(四大:多一个抽象)
封装:将数据和操作数据的方法有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装本质是一种对数据和操作的管理和规范。(类本身就是封装的体现)
类的实例化
创建一个类类型的变量的过程
变量:对象—>自定义类型的变量一般习惯称为对象
对象模型中只存放普通的成员变量,不存放成员函数(放在公共的代码段);空类的大小为1byte(字节)。
class A //4字节
{
int _a;
};
class B //4字节
{
int _b;
void fun1()
{
int a = 1;
float b = 2.0;
char c = 'a';
}
};
class C //1字节
{
void fun1()
{
int a = 1;
float b = 2.0;
char c = 'a';
}
};
class D //1字节
{};
类的大小也遵循内存对齐的规则;嵌套类本身遵循内存对齐的原则。
类的大小遵循内存对齐规则
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍地址处。 (对齐数 = 编译器默认对齐数与该成员大小的较小值,VS默认为 8 ,Linux和当前字段sizeof值一样)。
- 结构体总大小为:最大对齐数(所有变量类型的最大者与默认对齐数取最小)的整数倍。
- 如果存在嵌套,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍处。
如果嵌套的结构体只有定义,那么算大小的时候不算它!
class A //48 字节
{
char _a;
double _b;
int _c;
char _d;
class B
{
double _a;
char _b;
int _c;
char _d;
};
B b;//关键点
};
class A //24字节
{
char _a;
double _b;
int _c;
char _d;
class B
{
double _a;
char _b;
int _c;
char _d;
};
};
为什么进行内存对齐,有什么好处?
答:提高访问效率,CPU读取内存是按块读取的,内存对齐可以提高访问效率,方便一些硬件(如嵌入式)读取数据(以空间换时间的做法,占更大的空间但是提高了效率)
如何修改内存对齐数:#pargma pack()
this指针
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
this指针类型:类类型*const
只存在于成员函数中,并且始终做成员函数的第一个形参,编译器自动传递,不需要显示定义此参数。this指针不算做类的成员,只作为函数的形参,一般存在栈上(一般会做优化,存放在寄存器上)。
this在不做解引用的场景下可以为空(做的话不能为空)