类和对象~

1.1 类定义格式

class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。
 为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加_或者m开头,注意C++中这个并不是强制的,只是一些惯例,具体看公司的要求。
 C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类, 明显的变化是struct中可以定义函数, 一般情况下我们还是推荐用class定义类。
定义在类面的成员函数默认为inline。

1.2访问限定符

c++一种实现封装的方式,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
public修饰的成员在类外可以直接被访问; protected和private修饰的成员在类外不能直接被访
问,protected和private是一样的,以后继承章节才能体现出他们的区别。
访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有
访问限定符,作用域就到}即类结束。
class定义成员没有被访问限定符修饰时默认为private,struct默认为public。
一般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。


2对象大小

内存对齐原则

第一个成员在与结构体偏移量为0的地址处。
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数=编译器默认的一个对齐数与 该成员大小的较小值。
VS中默认的对齐数为8
结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小
就是所有最大对齐数(含套结构体的对齐数)的整数倍。

例如:类和对象~_第1张图片

3、this指针

Date类中有Init与Print两个成员函数,函数体中没有关于不同对象的区分,那当d1调用Init和
Print函数时,该函数是如何知道应该访问的是d1对象还是d2对象呢?那么这里就要看到C++给了
一个隐含的this指针解决这里的问题
编译器编译后,类的成员函数默认都会在形参第一个位置,增加一个当前类类型的指针,叫做this
指针。

类的成员函数中访问成员变量本质上都是通过this指针访问的

C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内使用this指针

显面向对象三大特性:封装、继承、多态,
C++中数据和函数都放到了类里面,通过访问限定符进行了限制,不能再随意通过对象直接修改数
据,这是C++封装的一种体现,这个是最重要的变化。这里的封装的本质是一种更严格规范的管
理,避免出现乱访问修改的问题。

4.类的默认成员函数


默认成员函数就是用户没有显式实现,编译器会自动生成的成员函数称为然认成员函数一个类,我
们不写的情况下编译器会默认生成以下6个默认成员函数
第一:我们不写时,编译器默认生成的函数行为是什么,是否满足我们的需求。
第二:编译器默认生成的函数不满足我们的需求,我们需要自己实现,那么如何自己实现?

5.构造函数


构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象(我们常使用的局部对象是栈帧创建时,空间就开好了),而是对象实例化时初始化对象。构造函数的本质是要替代我们以前Stack和Date类中写的Init函数的功能,构造函数自动调用的特点就完美的替代的了Init。


构造函数的特点:
1.函数名与类名相同。
2.无返回值。(返回值啥都不需要给,也不需要写void,不要纠结,C++规定如此)
3.对象实例化时系统会自动调用对应的构造函数。
4.构造函数可以重载。
5.如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
6、无参构造函数、全缺省构造函数、我们不写构造时编译器默认生成的构造函数,都叫做默认构造函数。但是这三个函数有且只有一个存在,不能同时存在。无参构造函数和全缺省构造函数虽然构成函数重载,但是调用时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认生成那个叫默认构造,实际上无参构造函数、全缺省构造函数也是默认构造,总结一下就是不传实参就可以调用的构造就叫默认构造。
7、我们不写,编译器默认生成的构造,对内置类型成员变量的初始化没有要求,也就是说是是否初始化是不确定的,看编译器。对于自定义类型成员变量,要求调用这个成员变量的默认构造函数初始化。如果这个成员变量,没有默认构造函数,那么就会报错,我们要初始化这个成员变量,需要用初始化列表才能解决,初始化列表,我们下个章节再细细讲解。
说明:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的原生数据类型,如:int/char/double/指针等,自定义类型就是我们使用class/struct等关键字自己定义的类型。


总结:大多数情况,构造函数都需要我们自己去实现,少数情况类似MyQueue且Stack有默认构造时,MyQueue自动生成就可以用。应写尽写

6、析构函数


析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁,比如局部对象是存在栈帧的,
函数结束栈帧销毁,他就释放了,不需要我们管,C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。析构函数的功能类比我们之前Stack实现的Destroy功能


析构函数的特点:
1.析构函数名是在类名前加上字符~。
2.无参数无返回值。(这里跟构造类似,也不需要加void)
3.一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4.对象生命周期结束时,系统会自动调用析构函数。
5.跟构造函数类似,我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定类型成员会
调用他的析构函数
6.还需要注意的是我们显示写析构函数,对于自定义类型成员也会调用他的析构,也就是说自定义类型成员无论什么情况都会有动调用析构函数。
如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数;如
果默认生成的析构就可以用,也就不需要显示写析构;但是有资源申请时,一定要
自己写析构,否则会造成资源泄漏。

类和对象~_第2张图片


 


 

你可能感兴趣的:(c++)