小网站建设/百度云搜索资源入口
继承
- 一、初识继承
- 概念
- “登场”
- 语法格式
- 继承方式
- 九种继承方式组合
- 小结(对九种组合解释)
- 二、继承的特性
- 赋值转换 一一 切片 / 切割
- 作用域 一一 隐藏 / 重定义
- 三、派生类的默认成员函数
- 派生类的默认成员函数
- 1. 构造函数
- 2. 拷贝构造
- 3. 赋值运算符重载
- 4. 析构函数
- 四、延伸知识
- 1. 继承与友元
- 2. 继承与静态成员
- 五、单继承和多继承
- 单继承
- 多继承
- 菱形继承
- 菱形虚拟继承
- 语法
- 原理
- 总结
- 拓展知识:组合
一、初识继承
概念
继承:保持原有类特性的基础上进行扩展,增加功能,产生新的类。新的类就叫做派生类(子类),原有类就叫做基类(父类)。
继承的作用:继承机制是面向对象程序设计使代码可以复用的最重要的手段,继承是类设计层次的复用,呈现了面向对象程序设计的层次结构。
“登场”
class Person
{
public:void Print(){cout << "name:" << _name << endl;cout << "age:" << _age << endl;cout << endl;}protected:string _name = "张三";int _age = 18;
};//继承后,父类的Person成员(成员函数 + 成员变量)都会成为子类一部分
class Student : public Person
{
protected:int _stuId;
};int main()
{Student s;s.Print();return 0;
}
结论:代码体现出Student对Person的继承(复用)
语法格式
继承方式
继承方式和访问限定符:
九种继承方式组合
C++中的继承方式和访问限定符组合,形成了九种情况的继承结果
类成员/继承方式 | public继承 | protected继承 | private继承 |
---|---|---|---|
基类的public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成员 |
基类的protected成员 | 派生类的protected成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
eg:实例演示三种继承关系下基类成员的各类型成员访问关系的变化
class Person
{
public:void Print(){cout << "名字:" << _name << endl;}
protected:string _name = "张三";
private:int _age = 18;
};//class Student : protected Person
//class Student : private Person
class Student : public Person
{
protected:int _stuId = 111;
};int main()
{Student s;s.Print();return 0;
}
小结(对九种组合解释)
不需要全部记完,这两种是最常用的记住即可:
- 在九种组合表中,基类的私有成员是不可见的。基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符, 继承方式),(public > protected > private)。 Min:两者的较小者。
- 基类private成员在派生类中什么方式都不可见。不可见:基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能访问
- 基类成员不想在类外直接被访问,但要在派生类中能访问,就要定义为protected。保护成员限定符是因为继承才出现的
- 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public。建议:显示写
- 实际运用一般都是public继承,扩展维护性强
二、继承的特性
赋值转换 一一 切片 / 切割
派生类对象可以赋值给基类的对象 / 基类的指针 / 基类的引用。这个过程叫切片或者切割,不会产生临时变量,发生赋值兼容,就同把派生类中父类那部分切来赋值过去。
原理:(切片 / 切割)
eg:证明:不会产生临时变量
class Person
{
protected:string _name;string _sex;int _age;
};class Student : public Person
{
public:int _No;
};int main()
{int i = 0;//double& d = i; //errorconst double& rd = i; //int赋值给double类型的值,会产生临时变量,所以要+const//派生类对象可以直接赋值给基类对象,不要+const,也就证明,这个过程没有产生临时变量Student s;Person& p = s;return 0;
}
注意:派生类对象赋值给基类的对象(或者基类的指针,或者基类的引用)这个过程称为向上转换。
拓展(不作详细介绍): 基类的指针和引用可以通过强转赋值给派生类的指针或者引用,但基类的指针是指向派生类对象时才安全。-- 这个过程称为向下转换。注意:基类对象不能赋值给派生类对象。
eg:
class Person
{
//protected:
public:string _name = "peter";string _sex = "male";int _age = 18;
};class Student : public Person
{
public:int _No = 2140104111;
};int main()
{Student s;//1.派生类对象可以赋值给父类对象/指针/引用Person p = s;Person* ptrp = &s;ptrp->_age = 21;Person& rp = s;rp._name = "张三";//2.基类对象不能赋值给派生类对象//s = p; //errorreturn 0;
}
代码分析:
注意:使用保护继承,成员权限会发生变化
Person p = s; //就会出现错误
这是因为保护继承下,派生类的对象只能被派生类或派生类的子类引用,而不能被基类引用。
原理: 因为非公有派生类(私有或保护派生类)不能实现基类的全部功能,例如在派生类外不能调用基类的公用成员函数访问基类的私有成员。因此,只有公有派生类才是基类真正的子类型,它完整地继承了基类的功能。
作用域 一一 隐藏 / 重定义
- 在继承体系中基类和派生类都有独立的作用域
- 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问(子类成员隐藏父类成员),这叫做隐藏(或者重定义)。 (在子类成员中,可以 基类::基类成员 显示访问。但是指定作用域,如果找不到会直接报错,不会再去访问别的域。eg:派生类成员)
- 成员函数隐藏:函数名相同就构成隐藏
- 建议:最好不要定义同名成员
拓展:访问成员遵循就近原则(编译器既定顺序):局部域-当前类域-父类域-全局域
eg1:成员变量
class Person
{
protected:string _name = "张三";int _num = 111;
};class Student : public Person
{
public:void Print(){cout << "姓名:" << _name << endl;//指定显示访问cout << "Person::_num:" << Person::_num << endl;//默认访问子类。子类隐藏了父类cout << "_num:" << _num << endl;}protected:int _num = 999;
};int main()
{Student s;s.Print();return 0;
}//output:
//姓名:张三
//Person::_num:111
//_num : 999
eg2:成员函数
//fun不构成重载,因为不在同一作用域
//fun构成隐藏,成员函数满足函数名相同
class A
{
public:void fun(){cout << "fun()" << endl;}
};
class B : public A
{
public:void fun(int i){A::fun();cout << "fun(int i)->" << i << endl;}
};int main()
{B b;b.fun(1);//b.fun(); //参数不匹配//指定访问b.A::fun();return 0;
}//output:
//fun()
//fun(int i)->1
//fun()
三、派生类的默认成员函数
派生类的默认成员函数
演示代码:后面会分为四个部分进行拆分讲解
class Person
{
public://如果没有默认构造,必须在派生类的初始化列表显示调用//Person(const char* name)Person(const char* name = "peter"):_name(name){cout << "Person()" << endl;}Person(const Person& p):_name(p._name){cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){cout << "Person& operator=(const Person& p)" << endl;if (this != &p){_name = p._name;}return *this;}~Person(){cout << "~Person()" << endl;}protected:string _name;
};class Student : public Person
{
public:Student(const char* name, int num):Person(name), _num(num){cout << "Student()" << endl;}Student(const Student& s):Person(s), _num(s._num){cout << "Student(const Student& s)" << endl;}Student& operator=(const Student& s){cout << "Student& operator=(const Student& s)" << endl;if (this != &s){Person::operator=(s);_num = s._num;}return *this;}~Student(){cout << "~Student()" << endl;}protected:int _num;
};int main()
{Student s1("jack", 18); //构造函数Student s2(s1); //拷贝构造函数Student s3("rose", 17); s1 = s3; //赋值运算符重载return 0;
}
构造和析构调用和执行顺序图:
1. 构造函数
- 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认构造,则必须在派生类构造的初始化列表阶段显式调用
- 派生类对象初始化先调用基类构造再调派生类构造
eg1:(有默认构造)
class Person
{
public:Person(const char* name = "张三"):_name(name){cout << "Person()" << endl;}
protected:string _name;
};class Student : public Person
{
public:Student(const char* name, int num):_stuId(num){cout << "Student()" << endl;}
protected:int _stuId;
};int main()
{Student s("jack", 18);return 0;
}
代码F11逐语句执行过程:
eg2:(没有默认构造)
基类没有默认构造,在派生类必须显示调用,Person先初始化,然后是_stuId。(基类先声明,所以先初始化Person)
//没有默认构造
class Person
{
public:Person(const char* name):_name(name){cout << "Person()" << endl;}
protected:string _name;
};class Student : public Person
{
public:Student(const char* name, int num):Person(name) //在初始化列表调用基类默认构造。如同定义匿名对象, _stuId(num){cout << "Student()" << endl;}
protected:int _stuId;
};int main()
{Student s("jack", 18);return 0;
}
代码F11逐语句执行过程:
2. 拷贝构造
- 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化
演示代码的拷贝构造部分:
3. 赋值运算符重载
- 派生类的operator=必须调用基类的operator=完成基类的复制
4. 析构函数
- 派生类的析构会在调用完成后自动调用基类的析构函数清理基类成员。原因:为了保证派生类对象,先清理派生类成员再清理基类成员的顺序
- 因为后续的一些场景,析构函数要构成重写,重写的条件之一就是函数名相同。所以编译器对析构函数名进行特殊处理,处理成destructor()。所以父类析构函数不+virtual,子类析构函数和父类析构函数构成隐藏关系。
四、延伸知识
1. 继承与友元
友元关系不能继承,所以基类的友元不能访问子类私有成员和保护成员
eg:
class Student; //先声明,因为在Person中引用了Student对象
class Person
{friend void Dispaly(const Person& p, const Student& s);
protected:string _name = "张三";
};class Student : public Person
{
protected:int _stuId = 0;
};
void Dispaly(const Person& p, const Student& s)
{cout << s._name << endl; //okcout << p._name << endl; //okcout << s._stuId << endl; //error
}int main()
{Dispaly(Person(), Student());return 0;
}
注意:如果想要在Display()中调用s._stuId,要在Student类中也加上友元
2. 继承与静态成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员
class Person
{
public:Person(){++_count;}
protected:string _name;
public:static int _count;
};
int Person::_count = 0;
class Student : public Person
{
protected:int stuId;
};
class Graduate : public Student
{
protected:string _seminarCourse;
};int main()
{Student s1;Student s2;Student s3;Graduate s4;cout << "人数:" << Person::_count << endl;Graduate::_count = 0;cout << "人数:" << Person::_count << endl;return 0;
}//output:
//人数:4
//人数:0
注意:静态成员属于父类和派生类,在派生类不会单独再拷贝一份,继承的是使用权。eg:上面的代码使用的始终都是一个_count
五、单继承和多继承
单继承
单继承:一个子类只有一个直接父类时称这个关系为单继承
多继承
菱形继承
菱形继承:多继承的一种特殊情况。
菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承由数据冗余(浪费空间)和二义性(不知道访问谁) 问题,在Assistant的对象中Person成员有两份
菱形继承代码:
class Person
{
public:string _name;
};class Student : public Person
{
protected:int _stuId;
};class Teacher : public Person
{
protected:int _workId;
};class Assistant : public Student, public Teacher
{
protected:string _course;
};int main()
{Assistant a;//这样会有二义性问题,无法明确访问的哪一个//a._name = "peter"; //error//显示指定访问那个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy";return 0;
}
对于菱形继承解决不了的问题,出现了虚拟继承。
菱形虚拟继承
虚拟继承可以解决菱形继承的二义性和数据冗余问题。
语法
如上面菱形继承代码的继承关系,在Student和Teacher继承Person时使用虚拟继承。
eg:
原理
借用简化的菱形继承体系,通过内存窗口观察对象成员的模型
菱形继承
class A
{
public:int _a;
};class B : public A
{
public:int _b;
};class C : public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}
菱形虚拟继承
class A
{
public:int _a;
};class B : virtual public A
{
public:int _b;
};class C : virtual public A
{
public:int _c;
};class D : public B, public C
{
public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}
注意: D中为什么B和C部分要找属于自己的A
解释:
菱形虚拟继承的原理解释:
总结
- 虚拟继承的缺陷:虚拟继承会增加程序的复杂性,因为派生类需要特别处理虚基类的初始化和访问。虚拟继承还可能导致一些性能上的损失,因为派生类需要额外的指针来访问虚基类。-- 不建议使用菱形继承
- 继承和组合:
- public继承是一种is-a的关系。eg:植物和花
- 组合是一种has-a的关系。 eg:轮胎和车
拓展知识:组合
**优先使用对象组合,而不是类继承,**组合耦合度低,代码维护性好
- 白盒测试:知道底层
- 黑盒测试:不知道底层
- 继承,通过生成派生类的复用称为白箱复用(white-box reuse)。白箱(相对可视性而言):在继承方式中,基类内部细节对子类可见。继承一定程度破坏了基类的封装。耦合度高:基类的改变极大的影响派生类,两者关系紧密
- 组合,新的更复杂的功能可以通过组装或组合对象获得。被组合对象具有良好定义的接口。这种复用风格称为黑箱复用(black-box reuse),**对象内部细节不可见。**组合类之间没有很强的依赖关系,耦合度低
eg:
//继承
//Car和BMW Car和Benz构成is-a关系
class Car
{
protected:string _color = "白色";string _num = "陕IT6666";
};class BMW : public Car
{
public:void Drive(){cout << "好开" << endl;}
};class Benz : public Car
{
public:void Drive(){cout << "好坐" << endl;}
};//组合
//Tire和Car构成has-a关系
class Tire
{
protected:string _brand = "Michelin";size_t _size = 17;
};class Car
{
protected:string _color = "白色";string _num = "陕IT6666";Tire _t;
};
相关文章:

继承(C++)
继承 一、初识继承概念“登场”语法格式 继承方式九种继承方式组合小结(对九种组合解释) 二、继承的特性赋值转换 一一 切片 / 切割作用域 一一 隐藏 / 重定义 三、派生类的默认成员函数派生类的默认成员函数1. 构造函数2. 拷贝构造3. 赋值运算符重载4. …...

文心一言 VS 讯飞星火 VS chatgpt (80)-- 算法导论7.4 5题
五、如果用go语言,当输入数据已经“几乎有序”时,插入排序速度很快。在实际应用中,我们可以利用这一特点来提高快速排序的速度。当对一个长度小于 k 的子数组调用快速排序时,让它不做任何排序就返回。当上层的快速排序调用返回后&…...

SpringCloud 概述
文章目录 SpringCloud 概述一、微服务中的相关概念1、服务注册与发现2、负载均衡3、熔断4、链路追踪5、API网关 二、SpringCloud的介绍三、SpringCloud的架构1、SpringCloud中的核心组件(1)Spring Cloud Netflix组件(2)Spring Clo…...

Apache ShenYu 学习笔记一
1、简介 这是一个异步的,高性能的,跨语言的,响应式的 API 网关。 官网文档:Apache ShenYu 介绍 | Apache ShenYu仓库地址:GitHub - apache/shenyu: Apache ShenYu is a Java native API Gateway for service proxy, pr…...

uniapp 禁止遮罩层下的页面滚动
使用 touchmove.stop.prevent"toMoveHandle" 事件修饰符 若需要禁止蒙版下的页面滚动,可使用 touchmove.stop.prevent"moveHandle",moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。将这个方法直接丢到弹…...

postgresql 分组
postgresql 数据汇总 分组汇总聚合函数注意 总结 分组统计总结 高级分组总结 分组汇总 聚合函数 聚合函数(aggregate function)针对一组数据行进行运算,并且返回单个结果。PostgreSQL 支持以下常见的聚合函数: • AVG - 计算一…...

RT1052的EPWM
文章目录 1 EPWM介绍1.1 引脚1.2 时钟1.3 比较寄存器 2 函数 1 EPWM介绍 RT1052 具有 4 个 eFlexPWM(eFlexWM1~eFlex_PWM4)。 每个 eFlexPWM 可以产生四路互补 PWM即产生 8 个 PWM,也可以产生相互独立的 PWM 波。四路分别是模块0-3每个 eFlexPWM 具有各自的故障检…...

k8s 安装istio (一)
前置条件 已经完成 K8S安装过程十:Kubernetes CNI插件与CoreDNS服务部署 部署 istio 服务网格与 Ingress 服务用到了 helm 与 kubectl 这两个命令行工具,这个命令行工具依赖 ~/.kube/config 这个配置文件,目前只在 kubernetes master 节点中…...

vue 项目在编译时,总是出现系统崩的状态,报错信息中有v7 或者 v8 的样式-项目太大内存溢出
vue 项目在编译时,总是出现系统崩的状态,node 命令框也会报错,如下图:有v7 或者 v8 的样式。 原因分析: 分析:遇到与上面图片相似的问题,我们要首先要想到是否是 有关内存的问题,当然…...

低功耗蓝牙射频指纹识别
射频指纹 射频指纹是什么 射频指纹是一种利用无线电信号的特征来识别设备或用户的技术。射频指纹可以用来做设备身份认证、位置跟踪、安全防护等应用。射频指纹的优点是难以伪造、不依赖于额外的硬件或软件、适用于多种无线通信协议。 射频指纹识别流程 射频指纹识别的一般…...

怎么检测UI卡顿?(线上及线下)
什么是UI卡顿? 在Android系统中,我们知道UI线程负责我们所有视图的布局,渲染工作,UI在更新期间,如果UI线程的执行时间超过16ms,则会产生丢帧的现象,而大量的丢帧就会造成卡顿,影响用…...

Git 常用操作
一、Git 常用操作 1、切换分支 git checkout命令可以用于三种不同的实体:文件,commit,以及分支。checkout的意思就是对于一种实体的不同版本之间进行切换的操作。checkout一个分支,会更新当前的工作空间中的文件,使其…...

前端修改新增操作导致数据删除——js精度丢失
问题描述 笔者在写前端渲染表格的时候,发现无论是修改还是新增,数据都会被删除。检查了前端逻辑并与后端联调均无问题。 然后就开始和后端一起对数据库,结果发现,十几位的id,接收过来的时候,尾数均变为了…...

winform使用usercontrol 构建了一个复杂的列表,列表速度慢该如何优化?
当使用 WinForms 构建复杂的列表时,可能会面临性能问题,特别是在数据量大或 UI 复杂的情况下。以下是一些优化策略,可以帮助您改善列表的性能: 1. **虚拟模式 (Virtual Mode)**:对于大型数据集,考虑使用虚…...

Lnton羚通算法算力云平台如何在OpenCV-Python中使用cvui库创建复选框
CVUI 之 复选框 Python import numpy as np import cv2 import cvuidef checkbox_test():WINDOW_NAME Checkbox-Testchecked [False]# 创建画布frame np.zeros((300, 400, 3), np.uint8)# 初始化窗口cvui.init(WINDOW_NAME)while True:# 画布填色frame[:] (100, 200, 100…...

中项系统集成项目管理知识点汇总
中项系统集成项目管理知识点汇总 一、成本-进度二、十大管理及47个过程三、质量四、人力资源五、风险六、干系人沟通七、案例分析万能答案八、选择题知识点九、十大管理输入输出工具技术总结十大管理工具技术总结 一、成本-进度 针对进度滞后的绩效情况 /缩短工期,可…...

Docker容器:docker基础及网络
Docker容器:docker基础及安装 一.docker容器概述 1.什么是容器 (1)Docker是在Linux容器里运行应用的开源工具,是一种轻量级的“虚拟机”。 (2)是一个开源的应用容器引擎,基于go语言开发并遵…...

Django实现音乐网站 ⑿
使用Python Django框架制作一个音乐网站, 本篇主要是加载静态资源和推荐页-轮播图、推荐歌单功能开发。 目录 加载静态资源 引入jquery.js 引入bootstrap资源文件 创建基类模板样式文件 推荐页开发 轮播图开发 下载 加载swiper 自定义引入继承块设置 使用…...

ORB-SLAM2学习笔记10之图像关键帧KeyFrame
文章目录 0 引言1 KeyFrame类1.1 构造函数1.2 成员函数1.3 关键帧之间共视图1.3.1 AddConnection1.3.2 UpdateBestCovisibles1.3.3 UpdateConnections1.3.4 EraseConnection1.3.5 SetBadFlag 1.4 地图点1.5 生成树 2 KeyFrame用途 0 引言 ORB-SLAM2学习笔记7详细了解了System主…...

【ownCloud】添加信任域
在我进行使用mysql:5.6和 owncloud 镜像,构建一个个人网盘后 我的虚拟机更改了ip地址导致出现下列状况 报错:您正在访问来自不信任域名的服务器。 please contact your administrator. if you are an administrator of this instance, configure the &q…...

C++--类型转换
1.什么是类型转换 在传统C语言中,由强制类型转换和隐式类型转换,隐式类型转换,编译器在在编译阶段自动处理,能转换则转换,强制类型转换由用户自己转换。 缺陷: 转换的可视性比较差,所有的转换形…...

在服务器上部署 Nginx 并设置图片服务器
问题:我要指定/home/images专门存放图片!该怎么做,而且我的系统是centos8系统,只有一个root用户,用root用户已经安装了nginx 答案: 既然你使用了 CentOS 8,并且你想使用 /home/images 目录存放…...

使用NXP GUI GUIDER生成的GUI移植到雅特力MCU平台过程详解(ST/GD/国民/极海通用)
好记性不如烂笔头,既然不够聪明,就乖乖的做笔记,温故而知新。 本文档用于本人对知识点的梳理和记录 一、前言 上一篇我们有介绍NXP GUI Guider工具如何制作和调试GUI,GUI神器 NXP GUI GUIDER开发工具入门教程https://blog.csdn.n…...

JVM——配置常用参数,GC调优策略
文章目录 JVM 配置常用参数Java内存区域常见配置参数概览堆参数回收器参数项目中常用配置常用组合 常用 GC 调优策略GC 调优原则GC 调优目的GC 调优策略 JVM 配置常用参数 Java内存区域常见配置参数概览堆参数;回收器参数;项目中常用配置;常…...

使用IDEA把Java程序打包成jar
点击左上角File,选择Project Structure 左侧选中Artifacts,点击右侧的号 选择JAR->From modules with dependencies 选择你要运行的main方法所在的类,选好了点击OK Artifacts添加完成后点击右下角OK 在工具栏中找到Build,选择Build Artifacts 刚才创建好的Artifacts,选择Bui…...

元宇宙和数字孪生的异同探究
元宇宙和数字孪生,作为两个备受瞩目的概念,都在不同领域引起了巨大的关注。虽然它们都涉及数字化世界的构建,但元宇宙和数字孪生在概念、应用和影响方面存在一些异同点。 相似之处: 数字表示: 元宇宙和数字孪生都依赖…...

初识微服务
我们在曾经最常见的就是所谓的单体架构,但是由于网民越来越多,单体架构已经逐渐的被淘汰出去,所以我们在单体架构的基础上提出了微服务,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合࿰…...

数据库锁的分类 各种锁
锁的一个分类 数据库中的锁前言分享链接个人总结全局锁:表级锁行级锁: 数据库中的锁 前言 C支持并发有锁,Linux里面也有锁机制,数据库也有锁,什么互斥锁,表级锁,间隙锁,好多…&…...

MySQL数据库软件
MySQL数据库软件的详细知识介绍: 1. 存储引擎 MySQL支持多种存储引擎,如InnoDB、MyISAM等。不同引擎有各自的特点,InnoDB支持事务、行锁,MyISAM支持全文索引等。 2. 索引结构 MySQL索引主要有B树索引、哈希索引、全文索引等。这些索引通过不同的数据结构加速查找效率。 3. …...

无涯教程-PHP - preg_match_all()函数
preg_match_all() - 语法 int preg_match_all (string pattern, string string, array pattern_array [, int order]); preg_match_all()函数匹配字符串中所有出现的模式。 它将按照您使用可选输入参数order指定的顺序将这些匹配项放置在pattern_array数组中。有两种可能的类…...