面向对象和面向过程的初步认识
在学习C语言的时候,遇到一个问题的时候我们更关注于的是解决这个问题需要哪些步骤;因此称C语言为面向过程的语言。而面向对象的语言在遇到问题时则不再将重点放在过程上,而是将重点转移到解决这个问题需要的对象上。
面向过程:分析出求解问题的步骤,通过调用函数来逐步解决
面向对象:将一件事拆分成不同的对象,靠对象之间的交互解决问题
类的引入
在C语言中“struct”只能用来定义变量,而在C++中“struct”不但可以用来定义变量还可以定义函数。自此结构体升级成了类,在类中定义的变量叫做成员变量,在类中定义的函数称为成员函数或者成员方法,不过一般C++定义类时更喜欢用“class”关键字。
#include<iostream> using namespace std; typedef int DataType; struct Stack { void Init(size_t capacity) { _array = (DataType*)malloc(sizeof(DataType) * capacity); if (nullptr == _array) { perror("malloc申请空间失败"); return; } _capacity = capacity; _size = 0; } void Push(const DataType& data) { // 扩容 _array[_size] = data; ++_size; } DataType Top() { return _array[_size - 1]; } void Destroy() { if (_array) { free(_array); _array = nullptr; _capacity = 0; _size = 0; } } DataType* _array; size_t _capacity; size_t _size; }; int main() { Stack s; s.Init(10); s.Push(1); s.Push(2); s.Push(3); cout << s.Top() << endl; s.Destroy(); return 0; }
类的定义
定义方法于结构体几乎相同,只是关键字由“struct”替换成了“class”:
class ClassName //关键字接类名 { //这里面是类的主体,一般由成员变量和成员函数组成 }; //注意这里一定还要带分号
类的主体一般由成员变量和成员函数组成,但是,是把成员变量放在前面还是把成员函数放在前面这个并没有影响,因为C++认为一个类就是一个整体,并没有什么前后之分。(在C语言中是习惯先定义变量再使用),但是一般我们见到的C++程序都是将成员函数写在成员变量的前面,这是为什么呢?这里借用《高质量C/C++编程》一书来解释:
类的定义方法有两种,一种是将声明和定义放在一起,还有一种就是将声明和定义分开。
将声明和定义分离:
两种定义方法更推荐第二个,因为类中是可以写函数的所以可能导致一个类就会比较长,如果将声明和定义都写在一起想要快速弄清楚一个类的功能就会比较困难。为了方便阅读,更推荐将声明和定义分离。
一个小问题
类中又有变量又有函数,有时候会有变量名和函数参数名相同的情况,这个问题在初始化函数中体现的尤为明显:
虽然这样并没有什么错误,但是及其不方便阅读,很容易将自己搞晕,要解决这个问题有两个方法:一个是在成员变量前加上域作用限定符,还有一种则是在定义成员变量的时候给其加上一个标识符:
//1.加域作用限定符 class Date { public: void Init(int year, int month, int day) { Date::year = year; Date::month = month; Date::day = day; } private: int year; int month; int day; }; //2.给成员变量加标识符 class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; //标识符有多种,并不仅限于这一种表达方式具体还要看公司或者学校要求 };
类的访问限定符及封装
访问限定符
在类和对象阶段主要研究的是C++的封装,而C++实现封装的方法是用类将对象属性和方法结合到一块,让对象更加完善,通过访问权限选择性的将接口提供给外部的用户使用。
访问限定符说明
1.public修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4.如果后面没有访问限定符,作用域就到 } 即类结束。
5.class的默认访问权限为private,struct为public(因为struct要兼容C)
通常不希望成员变量在类外被访问,因此成员变量的访问限定符通常是private
注意: 访问限定符只在编译阶段有用,当数据映射到内存后,就没有任何访问限定符上的差别了。
【面试题】
在C++中class与struct有什么区别?
C++作为C语言的发展产物是兼容C语言的,因此struct关键字到了C++里不但可以继续用来定义结构体甚至还能定义类。但为什么大家更喜欢使用class来定义类呢?因为struct在定义类的时候默认权限是public,而class在定义类的时候默认权限是private。一般来说,并不喜欢在类外可以访问到成员变量。除此之外,在继承和模板参数阶段,struct和class也有一定的区别,这个后续给大家介绍。
封装
面向对象语言有三大特性:封装,继承,多态(并不是说只有三个特性,而是这三大特性比较出名)
在类和对象阶段主要研究的是封装,封装其实就是将数据和操作数据进行有机结合,隐藏对象的属性和实现细节,只对外公开接口来和对象交互。 那么为什么要有封装?封装本质上是一种管理,它可以让用户更方便使用。
比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。如果用户使用电脑还需要弄清楚cpu,显卡等内存元件是如何工作的,那计算机的使用门槛也太高了,计算机也就不能方便人们的生活了。从这里也可以看出封装是为了方便用户。
除此之外,封装有时候也是一种保护,在C语言实现栈时,取栈顶的元素也是用了函数封装起来的,并没有直接通过访问top变量来获得,这样其实是为了保护top变量的规范。
类的作用域
前面有提到,class创建出来的类默认权限是private,而且在声明类时我们通常会将类的权限设置为私有,这就产生了一个问题就是说定义在类外的函数无法访问成员变量:
这个问题的解决方法就是使用域访问限定符:
类的实例化
用类创建对象的的过程称为类的实例化,类是对对象进行描述的是一个模型一样的东西,限定了类有哪些成员并没有分配实际的内存空间来存储它。(声明是不会开空间的,只有定义以后才会开辟空间,可以说类其实就是一次声明,而类的实例化,其实就是类的定义。)
一个类可以实例化出多个对象。类就像设计图纸,而实例化对象就是根据设计图纸建造出来的房子。图纸并不能住人,只有图纸建造出来的房子才可以住人,同时一张图纸是可以建造出多个相同的房子的。