一,类的两种定义方式:
1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内
联函数处理。
1.声明和定义全部放在类中
2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
二,访问限定符说明
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
问题:C++中struct和class的区别是什么?
解答:C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
默认访问权限是private。注意:在继承和模板参数列表位置,struct和class也有区别
三,类的实例化
这里有三种不同的存储方式,我们一一举例分析
实例化的每个A对象成员变量都是独立空间,是不同变量,但是每个A对象调用PrintA成员函数都是同一个。我们通过反汇编可以看出调用的printa成员函数都是同一个地址,因此这种设计方式会随着类的实例化越来越多而造成浪费。
第二种方案采取把成员函数的地址用一个指针数组存储,并在类成员变量中存储指针数组的地址。但是这里并不采用第二种方案,取而代之采取第三种方案
内存对齐规则
同时这里类的存储同样遵从结构体内存对齐规则 ,这里我们列出结构体内存对齐规则
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
ps:当没有成员变量的空类存储时,会给一个字节来占位表示类的存在,否则当取地址时不好操作
四,this指针
当编译器编译时,会在前面加一个this指针,如下图所示:
在main函数调用参数时,同样也会在前面加上类的地址:
ps:this指针存储在栈中,因为它是一个形参
类的默认成员函数:
1.构造函数
当调用参数时,输入的参数格式不满足重载函数的格式,就会报错,例如这里只输入一个2022年分,所以一般构造函数建议使用全缺省函数
c++将类型分为两种:1.内置类型:double,int,long,指针等等 2.自定义类型:struct,class
而这里的默认构造函数对内置类型成员不做处理,自定义类型会调用默认构造函数
2.析构函数
析构函数: | 与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。 |
析构函数特征:
1. 析构函数名是在类名前加上字符 ~
2. 无参数无返回值类型
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
4. 对象生命周期结束时,C++编译系统系统自动调用析构函数
5.如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。
3.拷贝构造函数
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存
在的类类型对象创建新对象时由编译器自动调用
拷贝构造函数也是特殊的成员函数,其特征如下:
1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,
因为会引发无穷递归调用,想要拷贝就必须要传值,而这里的传值就是一种拷贝。
所以这里有两种解决方式:
1.用引用传参
2.指针传参
若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。