类与对象
- 一.面向对象的初步认识
- 二.初步认识类
- 三.类的权限
- 四.类的声明和定义
- 五.封装
- 六.类的实例化
- 七.类的大小
一.面向对象的初步认识
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
例如洗衣服
而C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
二.初步认识类
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数
这里是c语言实现的栈传送门,通过比较就可以知道为什么会出现类的概念了。
上面的struct stack就是一个类,可以把一个栈的多个功能写在一个花括号内。在c++中,上面的struct更喜欢用class替代。
三.类的权限
我们对上面的代码进行改进,将struct改成class。
但是编译器直接告诉我不可访问,为什么struct可以直接编过而class却不能呢?这就涉及到类的权限问题了。
访问权限分为三种
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
插个小帖子,现阶段认为私有和保护是一样的,直到继承时才进行区分。
简单来说,如果你想要函数能在外部被访问,就需要加上public
那么public的作用到哪里结束呢?直到遇到下一个限定符或者结束。
上面的public作用到private结束,private向下直到类结束。
总体来说struct和class是没有什么区别的,最大的不同就是struct默认权限是公有,class默认情况是私有,所以上面的代码直接将struct换成class是不可访问的。
四.类的声明和定义
类也可以声明和定义分离,那么是如何做到的呢?现在将上面的代码改造一下。
我们这里将init函数踢出,只在类里面声明,在fun.cpp里定义。
这样就可以实现类里函数声明和定义的分离。注意每一个类都是一个作用域,所以在定义时要加上域名,不然就会出现下面无法识别的问题。
这里编译器就不知道去哪里找_array,_size…符号。
那么我们可以在类里声明内联函数吗?
答案是不可以,内联函数的声明和定义是不可以分开的,具体原因大家可以看看这篇博客传送门
注意:在类里直接定义的函数会被默认为内联函数(这是c++的规定),所以如果一个函数过长,我们通常将其声明和定义分离出来。当然如果我们直接在类里定义了一个很长的函数,那么它真的就会变成内联函数吗?其实也不是,具体原因可以看看这篇博客传送门
顺便插一个不好的变成习惯
这里右边的year其实是init的参数year,因为优先使用局部域。private里的year是出于类域的。这里编译器不会报错,但很影响代码的可读性。
五.封装
在c语言中可以直接通过修改_array来达到目的,但这种操作是不规范的。在c++里我们将其设置为了私有,那么就可以强制程序员去调用函数来修改_array,规范了变成。
六.类的实例化
在上面的代码里,我们可以很明显的看到Init函数是声明,push,top…函数是直接在类里定义。那么下面的_array,_size…变量是声明还是定义呢?
答案都是声明。变量的声明和定义在于是否开辟空间。
这些变量并非一个一个定义的,而是一起定义的。而定义这些变量的过程就被称为类实例化对象或者对象定义。
这里举个例子,如果我们将pravate删掉,意味着这些变量可以直接访问,那么我们能直接赋值吗?
很明显是不能的,类就像是一张图纸,你很明显不能在图纸里放上一把椅子或者桌子,你必须依照图纸将这个房子的空间建出来,才能够往里面放入家具。
七.类的大小
我们创造了一个对象s,那么这个类的大小是多少呢?
答案是12。结论是对象中只储存成员变量,不储存成员函数。
我们应该怎样理解这个现象呢?其实也很简单,我们再创立一个对象。
两个对象的_size是一样的吗?很明显不是的。如果我们类比一下,就好像变量是每个房子的厕所,厨房…每个房子都要这些空间并且是独立的。而函数就像小区的花园,篮球场,多户人共用一个就可以了。(当然也可以每户人都建一个花园,但很明显太浪费了)
总结:每个对象所建立的对象都是独立的,而函数的调用都是同一个函数。