一、面向过程与面向对象的初步认识
C语言是 面向过程 的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
C++是基于 面向对象 的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
比如我们要实现一个外卖点餐系统:
面向过程:关注的是实现下单、接单、送餐这些过程。它体现到代码层面就是函数的实现;
面向对象:关注的是实现类对象及对象之间的关系,用户、商家、骑手以及他们之间的关系。体现到代码层面就是类的设计及类之间的关系;
二、类的引入
什么是类?
年龄作为类,可以包含青少年、中年人、老年人;学生作为类,可以包含姓名、学号、班级;日期作为类,可以包含年、月、日;
从这里可以看出和C语言中的结构体很类似,但是在C++中把结构体升级为了类;在C语言中我们创建了结构体后,想要定义一个结构体的变量,常常是这样定义的:struct Student s1;在C++中可以不用加struct,直接用Student s2;来进行定义变量;但是这里不能称之为变量,而是对象(即s2是Student的一个对象);这样的目的就是为了去兼容C而设计的;
struct Student { char name[10]; int age; int id; }; int main() { struct Student s1;//兼容C 去使用 Student s2; //升级到类,Student类名,也是类型; strcpy(s1.name, "zhangsan"); s1.age = 18; s1.id = 001; strcpy(s2.name, "lisi"); s2.age = 20; s2.id = 002; return 0; }
三、类定义的两种方式
上图中的struct类,在C++中更喜欢用class来代替;
class className { // 类体:由成员函数和成员变量组成 }; // 一定要注意后面的分号
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号。类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。
1. 声明和定义全部放在类体中
struct Student { //成员变量 char _name[10]; int _age; int _id; //成员方法/成员函数 void Init(const char* name, int age, int id) { strcpy(_name, name); _age = age; _id = id; } void Print() { cout << _name << endl; cout << _age << endl; cout << _id << endl; } }; int main() { struct Student s1;//兼容C 去使用 Student s2; //升级到类,Student类名,也是类型; s1.Init("zhangsan", 18, 1); s2.Init("lisi", 19, 2); s1.Print(); s2.Print(); return 0; }
2. 声明放在.h文件中,类的定义放在.cpp文件中
四、类的访问限定符及封装
1.封装
面向对象的三大特性: 封装、继承、多态 。
在类和对象阶段,我们只研究类的封装特性,那什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装本质上是一种管理:我们如何管理兵马俑呢?比如如果什么都不管,兵马俑就被随意破坏了。那么我们首先建了一座房子把兵马俑给封装起来。但是我们目的全封装起来,不让别人看。所以我们开放了售票通道,可以买票突破封装在合理的监管机制下进去参观。类也是一样,我们使用类数据和方法都封装到一下。不想给别人看到的,我们使用protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访问。所以封装本质是一种管理。
2.访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符 | 访问权限 |
public(公有) | 类内与类外 |
protected(保护) | 类内 |
private(私有) | 类内 |
【访问限定符说明】
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. class的默认访问权限为private,struct为public(因为struct要兼容C)
注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
假如我们不想让外界访问我们的成员变量,仅仅里提供两个函数接口;
//定义了一个日期类 class Data { //公有部分包含了日期类的初始化和打印函数(成员函数) public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { cout << _year << "-" << _month << "-" << _day << endl; } //私有部分包含了年月日这些成员变量 private: int _year; int _month; int _day; }; int main() { return 0; }
当你在类中只有函数声明时,你想要在类的外部进行函数的定义;此时就需要用到作用域解析符 :: ;
//Stack.h class Stack { //共有部分只有函数声明,没有定义; public: void Init(); void Push(int x); private: int* _a; int _top; int _capacity; }; //Stack.c #include "Stack.h" void Stack::Init()//当我们在类外定义时,需要加上作用域解析符 ::,因为类的作用域仅仅只在类的内部 { _a = nullptr; _capacity = _top = 0; } void Stack::Push(int x) { }
五、类的实例化
用类类型创建对象的过程,称为类的实例化
1. 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
2. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量
3. 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
//定义了一个日期类 class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } void Print() { cout << _year << "-" << _month << "-" << _day << endl; } private: int _year; int _month; int _day; }; int main() { //将类Data实例化出多个对象 Date d1; Date d2; Date d3; Date d4; return 0; }