【C++】继承(详解)

前言:今天我们正式的步入C++进阶内容的学习了,当然了既然是进阶意味着学习难度的不断提升,各位一起努力呐。

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:高质量C++学习 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


什么是继承

C++中的继承是一种面向对象编程的特性,它允许一个类(子类)继承另一个类(父类)的属性和方法,并且可以添加自己的属性和方法。通过继承,子类可以重用父类的代码,减少重复编写代码的工作量。在C++中,使用关键字"extends"可以声明一个类继承另一个类。子类将自动继承父类的非私有成员和方法,并可以通过重写(override)父类的方法或添加新方法来实现自己的行为。(光看文字大家肯定还是觉得晦涩难懂的,我们直接看代码)


继承的使用格式

在C++中,使用继承的格式如下:

class 子类名 : 访问权限 基类名
{
    // 子类的成员和函数声明
};

其中,子类名表示要定义的子类的名称,访问权限可以是public、protected或private,用于指定从基类继承成员的访问权限,基类名表示要继承的基类的名称。

例如,定义一个基类(父类)father和一个派生类(子类)son:

class father//父类
{
public:
	string name = "张三";
	int age = 20;
};

class son: public father//public继承子类可以直接继承父类的公有对象
{
public :
	void print()
	{
		cout << name << endl << age << endl;
	}
};
int main()
{
	son s1;
	s1.print();
	return 0;
}

在上述例子中son是parent的子类,使用public权限继承了parent中name和age,然后用子类中的成员函数去调用print函数从而调用了父类中的成员。

结果如下:
在这里插入图片描述

如果还是不太能理解父类和子类的关系,看下图,通俗的理解就是儿子继承了父亲的遗产,并且儿子的财产依然存在。
在这里插入图片描述


继承后子类(派生类)的访问权限

在C++中,继承后的访问权限可以分为三种:public、protected和private。

公有继承(public inheritance):当通过公有继承派生一个子类时,基类的公有成员和保护成员在子类中仍然是公有的,可以直接访问。基类的私有成员在子类中是不可访问的。

保护继承(protected inheritance):当通过保护继承派生一个子类时,基类的公有成员和保护成员在子类中都变成了保护成员,它们通过子类只能被子类自身和子类的派生类访问,外部无法访问。基类的私有成员在子类中是不可访问的.。

私有继承(private inheritance):当通过私有继承派生一个子类时,基类的公有成员和保护成员在子类中都变成了私有成员,只能在子类内部访问,外部无法访问。基类的私有成员在子类中是不可访问的。

需要注意的是,继承的访问权限仅影响继承后的成员的访问权限,不会改变基类中成员本身的访问权限。
在这里插入图片描述

实例演示:

class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class PublicDerived : public Base {
public:
    void example() {
        publicMember = 10; // 可以直接访问公有成员
        protectedMember = 20; // 可以直接访问保护成员
        // privateMember = 30; 无法访问私有成员
    }
};

class ProtectedDerived : protected Base {
public:
    void example() {
        publicMember = 10; // 可以直接访问公有成员
        protectedMember = 20; // 可以直接访问保护成员
        // privateMember = 30; 无法访问私有成员
    }
};

class PrivateDerived : private Base {
public:
    void example() {
        publicMember = 10; // 可以直接访问公有成员
        protectedMember = 20; // 可以直接访问保护成员
        // privateMember = 30; 无法访问私有成员
    }
};


总结:

  1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
  2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他
    成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected > private。
  4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
  5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
  6. 很多人分不清保护继承和私有继承,其实区别就是保护继承他的儿子的儿子也能访问他的保护成员和公有成员,私有继承就是只有他儿子能访问。

子类与父类

子类与父类的相互赋值转换

  1. 符号赋值“=”

注:这里我们先暂时知道赋值的规则就是切片赋值,就是把子类中的父类那部分,赋值过去即可。

在C++中,子类对象可以被隐式地转换为父类对象,但是父类对象不能被隐式地转换为子类对象。这是因为子类对象继承了父类对象的成员和方法,但父类对象并不包含子类特有的成员和方法。

以下是一个示例说明子类对象转换为父类对象的情况:

class Parent {
public:
    void print() {
        std::cout << "Parent class" << std::endl;
        std::cout << age << std::endl;
    }
    int age = 30;
};

class Child : public Parent {
public:
    void print() {
        std::cout << "Child class" << std::endl;
    }
};

int main() {
    Child child;
    child.age = 50;
    Parent parent = child;  // 子类对象隐式转换为父类对象
    parent.print();  // 调用父类的print()方法
    return 0;
}
  1. 引用
Child s1;//子类
	Parent& t1=st;//父类,通过引用对其进行赋值
  1. 指针
Child s1;//子类
	Parent* t1 = &st;//父类,通过指针进行赋值

总结来说,C++中可以将子类对象隐式地转换为父类对象,但是父类对象无法隐式地转换为子类对象。如果需要使用子类特有的成员和方法,需要进行类型转换.


同名成员变量

在C++中,当子类继承了父类时,如果子类中出现了与父类同名的成员变量,那么子类的同名成员变量会隐藏父类的同名成员变量。这称为"隐藏"(hiding)。

具体来说,如果子类定义了与父类同名的成员变量,那么子类中的同名成员变量会隐藏父类中的同名成员变量。这意味着当通过子类对象访问同名成员变量时,会优先访问子类中的成员变量,而无法直接访问到父类中的同名成员变量。

#include <iostream>
class Parent {
public:
    int num = 10;
};

class Child : public Parent {
public:
    int num = 20;
};

int main() {
    Child child;
    std::cout << "Child num: " << child.num << std::endl;   
    // 编译器还是就近原则,优先访问子类中的num,输出: Child num: 20
    std::cout << "Parent num: " << child.Parent::num << std::endl; 
    //想要访问父类中的num,需要指定类域,输出: Parent num: 10
    return 0;
}

在这里插入图片描述

在上面的示例中,Parent类中定义了一个名为num的成员变量,初始值为10。Child类继承了Parent类,并定义了一个同名成员变量num,初始值为20。

在main函数中,我们创建了Child类的对象child。当我们通过子类对象child访问num时,会优先访问子类的同名成员变量,因此输出结果为20。如果我们需要访问父类中的同名成员变量,可以使用作用域解析符"::"来指定父类,如child.Parent::num


同名成员函数

在C++中,当子类继承了父类时,如果子类中出现了与父类同名的成员函数,那么子类的同名成员函数将隐藏父类的同名成员函数。

具体来说,如果子类定义了与父类同名的成员函数,那么子类中的同名成员函数将隐藏父类中的同名成员函数。这意味着当通过子类对象调用同名成员函数时,会优先调用子类中的成员函数,而无法直接调用到父类中的同名成员函数。

然而,与成员变量的隐藏不同的是,对于成员函数的隐藏,如果需要在子类中使用父类的同名成员函数,可以使用作用域解析符"::"来指定父类.

class Parent {
public:
    void print() {
        std::cout << "Parent print" << std::endl;
    }
};

class Child : public Parent {
public:
    void print() {
        std::cout << "Child print" << std::endl;
        Parent::print();//可以通过指定域来调用
    }
};

int main() {
    Child child;
    child.print();                // 输出: Child print
    child.Parent::print();        // 输出: Parent print

    return 0;
}



子类中的默认成员函数

构造函数

在C++中,子类可以通过构造函数来初始化继承的父类成员。子类的构造函数可以调用父类的构造函数来初始化父类的成员变量。子类的构造函数在构造子类对象时被调用,而且会在子类构造函数的初始化列表中调用父类的构造函数.

注: 编译器会默认先调用父类的构造函数,再调用子类的构造函数.

class Parent
{
public:
	Parent(string name = "Dad", int age = 30)
		:_name(name)
		,_age(age)
	{
		cout << "这是父类:" << _name << " " << age << endl;
	}

protected:
	string _name;
	int _age;
};

class Child: public Parent
{
public:
	Child(string son)
		:_son(son)
	{
		cout << "这是子类:" << _son << endl;
	}

protected:
	string _son;
};

int main()
{
	Child s1("son");

	return 0;
}

在这里插入图片描述
这里我们可以明显的知道,编译器先调用父类的默认构造,在调用子类的构造,所以一定要保证这里的父类的构造是有效的,以防止构造失效.


析构函数

在C++中,子类可以定义自己的析构函数,用来释放子类对象在内存中分配的资源。子类的析构函数与基类的析构函数类似,通过在类的声明中使用特殊的名称~类名()来定义。

子类的析构函数会自动调用基类的析构函数,以确保基类对象中分配的资源被正确释放。

注: 析构函数和构造函数相反,编译器默认先调用子类的析构函数,再调用父类的析构函数.

实例演示:

class Parent
{
public:
	~Parent()
	{
		cout << "这是父类的析构" << endl;
	}
protected:
	string _name;
	int _age;
};

class Child: public Parent
{
public:
	~Child()
	{
		cout << "这是子类的析构" << endl;
	}
protected:
	string _son;
};

int main()
{
	Child s1;
	return 0;
}

在这里插入图片描述


拷贝构造

在C++中,子类可以定义自己的拷贝构造函数,用于创建一个新的子类对象,该对象与已存在的子类对象具有相同的值。

注: 子类的拷贝构造函数会自动调用基类的拷贝构造函数,以确保基类对象的成员变量得到正确的复制.

class Parent
{
public:
	Parent(string name = "Dad", int age = 30)
		:_name(name)
		, _age(age)
	{
		cout << "这是父类:" << _name << " " << age << endl;
	}

protected:
	string _name;
	int _age;
};

class Child : public Parent
{
public:
	Child(string son)
		:_son(son)
	{
		cout << "这是子类:" << _son << endl;
	}
	Child(Child& child)
		:Parent(child)//通过切片的方式直接对父类进行了初始化
		,_son(child._son)
	{
		cout << "拷贝构造:" << _name << " " << _age << " " << _son << endl;
	}
protected:
	string _son;
};

int main()
{
	Child s1("son");
	Child s2(s1);
	return 0;
}

在这里插入图片描述


赋值运算符重载

子类的赋值运算符重载函数可以用来实现对象之间的赋值操作,包括赋值基类对象的成员变量和子类对象的成员变量。在赋值过程中,可以先调用基类的赋值运算符重载函数来赋值基类对象的成员变量,然后再进行子类对象的成员变量的赋值操作.

class Parent
{
public:
	Parent(string name = "Dad", int age = 30)
		:_name(name)
		, _age(age)
	{
		cout << "这是父类:" << _name << " " << age << endl;
	}
	Parent& operator=(const Parent& s1)
	{
		if (this != &s1)
		{
			cout << "调用父类" << endl;
			_name = s1._name;
			_age = s1._age;
		}
	}

protected:
	string _name;
	int _age;
};

class Child : public Parent
{
public:
	Child(string son)
		:_son(son)
	{
		cout << "这是子类:" << _son << endl;
	}
	Child(Child& child)
		:Parent(child)
		,_son(child._son)
	{
		cout << "拷贝构造:" << _name << " " << _age << " " << _son << endl;
	}
	Child& operator=(const Child& s1)
	{
		if (this != &s1)
		{
			Parent::operator=(s1);//调用父类的运算符重载,以免调用自身造成栈溢出
			_son = s1._son;

		}
	}
protected:
	string _son;
};

int main()
{
	Child s1("son");
	Child s2(s1);
	return 0;
}

继承中的单继承与多继承

在C++中,单继承和多继承是两种不同的继承方式。

  1. 单继承:
    单继承指的是一个派生类只能继承自一个基类(一个孩子一个父亲)。在单继承中,一个派生类可以继承基类的所有成员(包括成员函数和成员变量),并且可以通过派生类对象访问这些成员。单继承的语法如下:

    class Base {
      // base class members
    };
    
    class Derived : public Base {
      // derived class members
    };
    

    在这个例子中,Derived类从Base类单继承,Derived类可以访问Base类中的所有公有成员。

  2. 多继承:
    多继承指的是一个派生类能够从多个基类继承。在多继承中,一个派生类可以继承多个基类的成员,这些成员可以通过派生类对象访问(一个孩子有多个父亲)。多继承的语法如下:

    class Base1 {
      // base class 1 members
    };
    
    class Base2 {
      // base class 2 members
    };
    
    class Derived : public Base1, public Base2 {
      // derived class members
    };
    

    在这个例子中,Derived类从Base1类和Base2类多继承,Derived类可以访问Base1Base2类中的所有公有成员。

需要注意的是,多继承在设计上可能会引入复杂性和冲突,需要谨慎使用。在多继承中,如果多个基类具有相同的成员函数或成员变量,派生类必须显式指明使用哪个基类的成员。另外,多继承还可能导致菱形继承问题,即继承图中出现多个路径指向同一个基类。为了解决这个问题,可以使用虚继承或其他技术。

总结起来,单继承和多继承是C++中的两种继承方式。单继承指的是派生类只能继承自一个基类,而多继承则允许派生类从多个基类继承。使用继承时需要考虑设计的简洁性和灵活性,以及可能引入的复杂性和冲突。


菱形继承

C++中的菱形继承(diamond inheritance)是多继承的一个特殊情况。当一个派生类通过两个不同的路径继承自同一个基类时,就会形成菱形继承结构。这种继承结构的名称源于它的图形表示类似于菱形。

考虑以下示例代码:

class A {
public:
    void funcA() {
        cout << "A::funcA()" << endl;
    }
};

class B : public A {
public:
    void funcB() {
        cout << "B::funcB()" << endl;
    }
};

class C : public A {
public:
    void funcC() {
        cout << "C::funcC()" << endl;
    }
};

class D : public B, public C {
public:
    void funcD() {
        cout << "D::funcD()" << endl;
    }
};

在这里插入图片描述

在这个例子中,类D通过BC两个路径分别继承了类A,形成了菱形继承结构。这意味着类D会有两份来自A类的成员函数和成员变量。例如,D类实例可以调用funcA()方法两次,一次是通过B的路径,另一次是通过C的路径。

菱形继承可能导致以下问题:

  1. 虚函数二义性(Virtual Function Ambiguity):如果在菱形继承结构中,派生类中存在同名的虚函数,那么在派生类中访问这个虚函数时将产生二义性,编译器不知道应该使用哪个父类的虚函数实现。

  2. 数据冗余(Data Redundancy):由于菱形继承结构中派生类从两个不同的路径继承了同一个基类,导致派生类中会存在两份相同的成员变量。

为了解决菱形继承带来的问题,可以使用以下方法:

  1. 虚拟继承(Virtual Inheritance)是C++中一种特殊的继承方式,用于解决多继承中的菱形继承问题。通过使用虚拟继承,可以确保在派生类中只包含一个共享的基类子对象,避免了数据冗余和虚函数二义性的问题。

虚拟继承的特点有:

虚拟继承只发生在最顶层的派生类中,而不会在派生类的派生类中发生。也就是说,只有直接派生自基类的派生类才能使用虚拟继承。

虚拟继承会在内存布局中引入一个额外的指针(虚表指针)来维护虚拟继承的关系。这个指针指向了虚拟基类的子对象,用于访问虚基类的成员。

如果虚拟基类有自己的派生类,那么虚拟继承会优先选择这个派生类中的虚基类子对象作为共享对象

  1. 重写和调用具体的父类函数:通过在派生类中重写同名的虚函数,并在派生类中显式调用具体的父类函数,可以解决虚函数二义性的问题。

综上所述,菱形继承是C++多继承的一个特殊情况,可能会引发虚函数二义性和数据冗余的问题,可以通过虚继承和重写父类函数的方式来解决这些问题。


好啦,今天的内容就到这里啦,下期内容预告C++中的多态.


结语:进阶的内容有点繁杂,大家一起加油呐!。


🌏🗺️ 这里祝各位接下来的每一天好运连连 💞💞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/761410.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2065. 最大化一张图中的路径价值 Hard

给你一张 无向 图&#xff0c;图中有 n 个节点&#xff0c;节点编号从 0 到 n - 1 &#xff08;都包括&#xff09;。同时给你一个下标从 0 开始的整数数组 values &#xff0c;其中 values[i] 是第 i 个节点的 价值 。同时给你一个下标从 0 开始的二维整数数组 edges &#xf…

电子技术基础(模电部分)笔记

终于整理出来了&#xff0c;可以安心复习大物线代了&#xff01;&#xff01; 数电部分预计7.10出

007-GeoGebra基础篇-构建等边三角形

今天继续来一篇尺规作图&#xff0c;可以跟着操作一波&#xff0c;刚开始我写的比较细一点&#xff0c;每步都有截图&#xff0c;后续内容逐渐复杂后我就只放置算式咯。 目录 一、先看看一下最终效果二、本次涉及的内容三、开始尺规画图1. 绘制定点A和B2. 绘制线段AB3. 以点A为…

【日记】度过了一个堕落的周末……(184 字)

正文 昨天睡了一天觉&#xff0c;今天看了一天《三体》电视剧。真是堕落到没边了呢&#xff08;笑。本来想写代码完成年度计划&#xff0c;或者多写几篇文章&#xff0c;但实在不想写&#xff0c;也不想动笔。 感觉这个周末什么都没做呢&#xff0c;休息倒是休息好了。 今天 30…

基于x86/ARM+FPGA+AI工业相机的智能工艺缺陷检测,可以检测点状,线状,面状的缺陷

应用场景 缺陷检测 在产品的制造生产环节中发挥着极其重要作用。智能工业缺陷检测能够替代传统的人工检测&#xff0c;降低人为判断漏失&#xff0c;使得产品质量大幅提升的同时降低了工厂的人力成本。智能工艺缺陷检测技术可以检测点状&#xff0c;线状&#xff0c;面状的缺陷…

UnityUGUI之四 Mask

会将上级物体遮盖 注&#xff1a; 尽量不使用Mask&#xff0c;因为其会过度消耗运行资源&#xff0c;可以使用Rect 2DMask&#xff0c;但容易造成bug&#xff0c;因此最好实现遮罩效果的方式为自己写一个mask物体

用易查分下发《致家长一封信》,支持在线手写签名,一键导出PDF!

暑假来临之际&#xff0c;学校通常需要下发致家长信&#xff0c;以正式、书面的形式向家长传达重要的通知或建议。传统的发放方式如家长签字后学生将回执单上交&#xff0c;容易存在丢失、遗忘的问题。 那么如何更高效、便捷、安全地将致家长一封信送达给每位家长呢&#xff1f…

项目方案:社会视频资源整合接入汇聚系统解决方案(八)---视频监控汇聚应用案例

目录 一、概述 1.1 应用背景 1.2 总体目标 1.3 设计原则 1.4 设计依据 1.5 术语解释 二、需求分析 2.1 政策分析 2.2 业务分析 2.3 系统需求 三、系统总体设计 3.1设计思路 3.2总体架构 3.3联网技术要求 四、视频整合及汇聚接入 4.1设计概述 4.2社会视频资源分…

多片体育场地建球馆,就选气膜球馆—轻空间

随着现代社会对健康生活的追求日益增加&#xff0c;体育场地的需求也在不断增长。尤其是羽毛球作为一项受欢迎的全民运动&#xff0c;其场地需求量更是与日俱增。在众多的球馆建设方案中&#xff0c;气膜球馆因其独特的优势&#xff0c;正逐渐成为多片体育场地建设的最佳选择。…

微尺度气象数值模拟—大涡模拟技术

原文链接&#xff1a;微尺度气象数值模拟—大涡模拟技术https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247607904&idx4&snc02e7b7b104c500626cc7456c819112a&chksmfa826787cdf5ee91860e66b4f45532b995760edc1780cdde52bb8b36349b9b997392d21aed18&…

为什么安装了SSL证书还是不能HTTPS访问?

即便是正确安装了SSL证书&#xff0c;有时网站仍然无法通过HTTPS正常访问&#xff0c;这背后可能隐藏着多种原因。以下是一些常见的问题及解决方案&#xff0c;帮助您排查并解决这一困扰。 PC点此申请&#xff1a;SSL证书申请_https证书下载-极速签发 注册填写注册码230918&a…

mysql-5.6.26-winx64免安装版本

mysql为什么要使用免安装 MySQL 提供免安装版本主要有以下几个原因和优势&#xff1a; 便捷性&#xff1a;用户无需经历安装过程&#xff0c;直接解压即可使用。这对于需要快速部署环境或者在不支持安装权限的系统上使用MySQL非常有用。灵活性&#xff1a;免安装版允许用户将…

基于SSM的挂号系统(简单)

设计技术&#xff1a; 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SSMJSP 工具&#xff1a;IDEA、Maven、Navicat 主要功能&#xff1a; 首页 登录 查看医生信息 挂号 挂号记录查看 个人信息查看 需要可加V分享源码 package com.hg.controller;impor…

idk17配置

只需要把zip包解压&#xff0c;然后配置环境变量&#xff1a; bin目录路径粘到path里面就好了 然后打开cmd窗口分别输入 java javac java -version 验证

IT专业入门,高考假期预习指南

文章目录 一、了解IT专业的基本概念二、选择适合的编程语言入门三、掌握基本的编程工具和环境四、学习基础的数据结构和算法五、实践项目和动手实验六、利用在线资源进行学习七、参加编程竞赛和社区活动总结 高考结束后&#xff0c;许多同学将迎来大学生活&#xff0c;而对于选…

ARP 原理详解 二

只要确定了 IP 地址后&#xff0c;就能够向这个 IP 地址所在的主机发送数据报&#xff0c;这是我们所熟知的事情。 但是再往深了想&#xff0c;IP 地址只是标识网络层的地址&#xff0c;那么在网络层下方数据链路层是不是也有一个地址能够告诉对方主机自己的地址呢&#xff1f…

【Python画图-循环01】一文叫你搭建python画图最优环境配置

【Python画图-循环01】一文叫你搭建python画图最优环境配置 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#…

突发!1本“On Hold”期刊惨遭除名!共12本期刊被剔除!Scopus目录更新!

【欧亚科睿学术】 近期&#xff0c;爱思唯尔更新了Scopus期刊目录&#xff0c;这是本年度的第五次更新。 图片来源&#xff1a;Elsevier 本次Scopus来源出版物列表(Scopus Sources)共有46097本期刊被收录。其中&#xff0c;有12本期刊不再被数据库收录(Discontinued titles)&a…

复制 pdf 的表格到 markdown 版本的Typora 或者 word 中

在 pdf 中选中复制表格内容&#xff0c;直接粘贴到 typora 中失败&#xff0c;可以使用 txt文件和 excel 做过渡。 准备一个空的 txt 文件&#xff0c;将 pdf 中表格的数据复制粘贴到txt文件中&#xff0c;文本内容会以空格分开&#xff0c;如下图的形式&#xff1a; 打开 exc…

[Shell编程学习路线]——shell脚本中case语句多分支选择详解

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f6e0;️Shell编程专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年6月21日16点30分 &#x1f004;️文章质量&#xff1a;95分 ————前言———— 在Shell编程中&#xff0c;处理多种条件…