目录
1.面向过程和面向对象初步认识
- 面向过程(Procedure Oriented 简称 PO):把事情拆分成几个步骤(相当于拆分成一个个的方法和数据),然后按照一定的顺序执行。
- 面向对象(Object Oriented 简称 OO):面向对象会把事物抽象成对象的概念,先抽象出对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法。
- 对象:对象是类的实例,一个对象必须属于一个自己的类,因此在定义对象前,必须要定义好自己所属的类。
- 类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。(类似C语言中的结构体)
- C语言是面向过程的,关注的是过程/步骤,分析出求解问题的步骤,通过函数调用逐步解决问题。
- C++是基于面向对象的,关注的是对象/对象和对象之间的关系,将一件事情拆分成不同的对象,靠对象之间的交互完成。
举例:以洗衣服和晒衣服这件事为例。
- C语言更加关注的是整个过程/步骤。
- C++更加关注的是对象,然后才是过程。
2.类的引入
C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数。比如:之前在数据结构初阶中,用C语言方式实现的栈,结构体中只能定义变量;现在以C++方式实现,会发现struct中也可以定义函数。
- C with class
- C++兼容C,所以C++同时兼容struct 的用法,但结构体同时升级成了类。
- C++类就是C中的结构体
- 类内不仅可以定义变量,也可以定义函数(成员函数)
- 类的实例化可以直接使用类名(类 对象)
- 一个类就是一个域(类域),不同类的相同函数名就不用区分了
- 访问类的成员变量/函数(无论对象/指针 访问方式和结构体一样 )
- 除了指针的访问,成员函数有点特殊后面讲解
一个类怎么设计,取决于类(成员变量/属性)要实现什么功能,方法。(成员函数)
#include<stdlib.h>
#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;
}
上面结构体的定义,在C++中更喜欢用class来代替。class和struct这两个关键字有什么区别呢?
3.类的定义
3.1类的定义规则
class为定义类的关键字,ClassName为类的名字,{ }中为类的主体,注意类定义结束时后面分号不能省略。
类体中内容称为类的成员:
- 类中的变量称为类的属性或成员变量;
- 类中的函数称为类的方法或者成员函数。
class className
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
【日期类】是我们后面讲解常用的例子。
class Date
{
//
};
//称"日期类"
3.2关键字class和struct的区别
class和struct有两个不一样,其他均一样
- struct兼容C/C++的用法,class不兼容只能使用C++的用法。
- 关于类的访问限定符:struct默认是公有的public,class默认是私有的private(因为struct要兼容C)>>?访问限定符后面细讲
3.3两种定义方式(声明和定义分离否)
类的两种定义方式:
- 1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
- 2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
- 一般情况下,更期望采用第二种方式。注意:上课为了方便演示使用方式一定义类,大家后序工作中尽量使用第二种。
【方法1:声明和定义不分离】
声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内
联函数处理。
【方法2:声明和定义分析】
类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::
- 类域:类里面也是一个域(花括号里面也是一个域)
- 类域可以顺便解决解决命名冲突的问题
- 搜索原则:1.局部优先 2.再类域 3.全局域
- 注意:缺省参数只在声明里面(类域),不在定义里面。
- 注意:成员函数名前需要加类名::
//test.h
#pragma once
#include<stdlib.h>
#include<iostream>
using namespace std;
class Date
{
public:
void Init(int year = 7, int month = 7, int day = 7);
public:
int _year;
int _month;
int _day;
};
//test.cpp
#include"test.h"
void Date::Init(int year=8, int month, int day)//❌
{
_year = year;//代码的可读性不高
_month = month;
_day = day;
}
//project.cpp
#include"test.h"
int main()
{
Date s;
s.Init();
return 0;
}
3.4成员变量命名规则
一般像下面这种代码不好区分,代码的可读性不高。
所有为了区分:(只列举两种,根据实际情况区分,不强制要求,只要能区分即可)
- 可以在成员变量前加下划线
- 可以在成员变量前加D
class Date
{
public:
void Init(int year, int month, int day)
{
year = year;//代码的可读性不高
}
int year;
int month;
int day;
};
int main()
{
Date s;
s.Init(7, 7, 7);
return 0;
}
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};
// 我们看看这个函数,是不是很僵硬?
class Date
{
public:
void Init(int year)
{
// 这里的year到底是成员变量,还是函数形参?
year = year;
}
private:
int year;
};
// 所以一般都建议这样
class Date
{
public:
void Init(int year)
{
_year = year;
}
private:
int _year;
};
// 或者这样
class Date
{
public:
void Init(int year)
{
mYear = year;
}
private:
int mYear;
};
// 其他方式也可以的,主要看公司要求。一般都是加个前缀或者后缀标识区分就行。
4.类的访问限定符及封装
4.1访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
- 【访问限定符说明】
- 1. public修饰的成员在类外可以直接被访问
- 2. protected和private修饰的成员在类外不能直接被访问
- (此处protected和private是类似,后面继承有区别,现阶段更加喜欢私有private)
- 3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
- 4. 如果后面没有访问限定符,作用域就到 } 即类结束。
- 5. class的默认访问权限为private,struct为public(因为struct要兼容C)
class的默认访问权限为private(私有)- struct为public(公有)
- 所以如果我们在使用class的时候。可以实例化类,但是如果要访问类中的成员必须加上访问限定符才可以。
- ❗❗建议:无论关键字是class还是struct 都加上访问限定符。
- 一般一个类的成员:成员变量都是私有;成员函数都是公有。
【面试题】
问题:C++中struct和class的区别是什么?
解答:
- C++需要兼容C语言,所以C++中struct可以当成结构体使用。
- 另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类默认访问权限是private。
注意:在继承和模板参数列表位置,struct和class也有区别,后序给大家介绍。
#pragma once
#include<stdlib.h>
#include<iostream>
using namespace std;
class Date//1.哪种类型的访问限定符取决于class / struct
{
public:
void Init(int year = 7, int month = 7, int day = 7)
{
_year = year;//代码的可读性不高
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date s;
s.Init();
return 0;
}
4.2封装
【面试题】
面向对象的三大特性:封装、继承、多态。
在类和对象阶段,主要是研究类的封装特性,那什么是封装呢?解答:
- 封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
- 封装本质上是一种管理,让用户更方便使用类。
举例:
- 比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。
- 但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
- 对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。
- 因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
- 在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。
联系
- 在前面学习操作系统中,我们学习了"管理"的本质是:先描述再组织。实际上 面向对象 的过程就是:先描述再组织。这里的封装就是:描述,把数据的属性信息封装起来。
- C把数据和方法是分离的。
- CPP是把数据和方法都放到类里面。
- CPP的访问限定符取对成员进行限制,想要外界访问的就是公有的,不想要给到外界访问的就是私有的。
- C++中成员变量一般用私有保护,成员函数大多公有保护,少数私有保护。
🙂感谢大家的阅读,若有错误和不足,欢迎指正。