【C++类】序幕
抽象
“抽象”这个词太抽象,不好理解,看到这个词能想到什么呢?一片空白,我们看到别的词,还能想到对应的实物,但看到“抽象”,脑子一片空白,所以,不好理解。
类,恰恰就是这么个抽象的东西,所以,不形象,很难理解。但抽象的东西又至关重要,因为它是对物质本质的总结。就是,去掉画皮后,层层剥离,卸掉装之后,最核心的东西的。
类是类型的一种。
那么类型是什么?如果要创建一个类型,要解决3个问题。1、这个类型需要的内存;2、这个类型在内存中的位要如何解释;3、这个类型的对象可以执行哪些操作;这3个问题定义清楚了,就可以单独成立一个类型了。
回到类,类要作为一个单独的类型,也是要回答上述3个问题的。
但好在类不是从0开始。而在基于已有的类型组合成的。所以,没有那么原始。
接口
类是工具,通过类我们可以完成某种工作,我们可以根据我们要完成的工作,选择某个合适的类。
我们使用类完成各种任务,是通过类提供的各种函数(在类里,称函数为方法)来完成的,这些函数统称为接口。
简单说,类就是个中间商,通过这个中间商我们可以作成某些事,中间商提供接口,我们跟接口打交道。
类的定义:
私有部分-private:类,做为一个中间商,就会有秘密,就是作为一个中介的生存根本,就是不能给大家知道的,知道了他们就活不下去了,很容易被客户踢掉,客户自己干了。所以,这部分内容就要设置为私有的。一般是存储信息。
公开部分-public:作为中间商,它要和客户、上游生产商打交道,所以,肯定有一些东西要公开,比如,对客户,它要公开它有啥新产品可以卖给客户的。让大家知道它能干啥,大家才知道去找他。一般是方法(函数),访问存储信息或操作信息。
类默认是私有的,不需要特别说明。这点与结构体不同,结构体默认是公开的。
成员函数实现:
声明类之后,还要实现类,主要是实现类声明的方法。
一般,类声明和实现,是分开在两个文件里(注意这里说的“一般”,说明还有不一般的)。所以,在实现类的方法的时候,需要用作用域解析运算符::。来指定方法(函数)所属哪个类。函数头,如下图所示,函数名前面多个类名::。
其实,这个写法,也说明这个方法(函数)的作用域,就只是在这个类里。
现在说说“不一般”的情况,函数定义在类声明里。这时,这个函数默认是内联函数,关于内联函数,可以到这里复习C++函数总结-CSDN博客。
当然也可以在函数实现时,指定它是内联函数,就是在函数开始的地方用inline关键字开头。
但是,一般是定义在类声明的头文件里,因为内联函数,会在编译时,在调用的文件里复制一份函数,但这容易导致重复。所以,最好不要定义在类声明之外,容易冲突。
构造函数
非必须的,定义类时,没有写构造函数,编译器会自动创建一个隐式的构造函数。
什么是构造函数?为什么要构造函数?
回答这两个函数前,回到上面定义部分的私有部分和公有部分,为了保密,类,定义了私有的东西,这些东西只有类自己知道。这就有个问题,我们创建类的时候,它里面的变量要初始化,要给它一个值,怎么操作呢?因为是私有的,外部不能给它赋值,所以只能通过他自己把我们想给的初始值设置好。这个就是构造函数做的事,这就是为什么要一个构造函数。
就是在使用定义的类,创建一个实例时,给这个实例赋初始值,以及一些其它的初始化操作,这就是构造函数,是在创建类的实例时,自动执行。
很明显,构造函数自动执行,它跟其它普通函数不一样,它的定义方式自然也要不一样。要不怎么显得他特殊呢。特殊点:没有返回类型,不是void,而就是没有,什么都不写,名称是类的名称,如下构造函数的声明示例,另外构造函数的参数名称不能是类成员(相同会导致混淆)。
使用时,分显式调用和隐式调用。
显示:
隐式:
上述两种调用分别创建了类的实例food和garment。
给类初始化时,可以使用列表初始化语法,就是用{}将需要提供的值括起来,用,将值分隔。
默认构造函数:
构造函数通过重载可以有多个,所以一般要设置一个默认的构造函数。
默认构造函数:不接受任何参数的构造函数,或者都有默认值的构造函数。
析构函数:
这个名字起的不方便理解,如果起清扫函数或者收尾函数更贴切。顾名思义,收尾函数,就是在类结束时,进行打扫工作。主要就是释放不再使用的内存。
这个函数也是自动执行的,所以,形式上,也有一点特殊,声明示例如下(不是实现方式,实际方式前面还要加类名::。
const成员函数
如果成员函数限制它不能修改成员,那么声明原型和定义时,在“{”加个const。
this指针
指向调用成员函数的对象,就是自己,在类内部函数运行时,如何指代自己,就用this这个指针,在类外部这个this就没有什么用了。因为可以直接用类的实例名称。
类的常量
类里面如果要定义常量,不能用const……。因为类声明,只是描述类的形式,并不创建对象。所以,没有用。
要用常量,只能用枚举变量,(编译时,会将枚举名称用具体的值替换)。
关于枚举,延伸一下定义,在同一个作用域里,枚举量不能同名。要避免这种冲突,可以用enum class 枚举名{枚举量1,枚举量2……}进行作用域限制,通过枚举名::枚举量进行使用,解决冲突。总结:就是定义枚举时,多了个class。
或者静态变量,就是static……。这种有个不好的地方,就是如果这个类创建了10个实例,那么这10个实例都是共用这个变量的。这会导致,10个实例中某个实例修改了这个变量,其它几个实例引用时,也是改变了。
当然,一个人认为的坏处,另一个人可能觉正需要这种共用的,就变成了好处。总之就是按需选择吧。
区别类和对象
类是用户自定义的一种数据类型,同int/float/double一样。
对象是类的实例,是变量,如同整形变量,浮点型变量一样。只是在类这种类型时,称对象。因为类的对象(变量)多了很多函数(方法)。再叫变量,有点小看了类的实例。
关于类对象的存储,延伸一下,同一个类创建的对象,它们各自的变量有自己的存储地方,但是方法(函数)是共用同一个存储地址的。就是说,一个类的方法,只存了一份,无论你创建10个对象还是100个对象,函数都只存在份。
总结
这篇介绍了类的主要概念,用于复习。
为什么分私有和公有,要定义常量怎么操作,初始化怎么做(构造),收尾怎么做(析构)。还没有进入到复杂的使用中。只是概念。