• 28.【继承与派生 (详解)】


    (一)、什么是继承与派生

    (1).继承是自然界一个普遍的重要特性,源于人们对客观世界的认识。(狗和黑狗的特性)一般到特殊的关系.

    (2).继承机制,就是在一个已存在的类(父类)的基础上建立一个新的类,这个新的类**(子类)自动拥有已有类的全部成员的一种机制**,进而体现出层次性.(下层是上层的特殊类)

    (3).继承是类之间定义的一种重要关系,已有类A的基础上定义类B,类B会自动得到类A的函数成员和数据成员,使得程序员只需在类B定义类A中所没有的新成分就柯完成在类B的定义,
    在这种情况下,就称类B继承了类A,类A派生了类B,A是基类(父类),B是派生类(子类),这种机制叫做继承

    (二)、为什么要使用继承和派生?

    类的继承和派生机制使程序员无需修改已有的类,只需在既有类的基础上,根据问题的实际需要,通过增加部分代码或修改少量代码而得到的新的类(派生类),从而解决了程序代码的重用问题.

    (三)、继承方式

    公有继承,私有继承,保护继承,

    如果缺省:就是声明的时候继承方式是空的,那就默认为是按照私有继承方式继承.

    (四)、继承的属性

     (1).继承基类的成员函数和数据成员
     (2).增加新的数据成员和成员函数.
     (3).重载或重新定义继承自基类的成员函数
     (4).改变基类成员在派生类中的访问属性
    
    • 1
    • 2
    • 3
    • 4

    1.添加新的数据成员和成员函数

    
    #include 
    using namespace std;
    class Base    
    {
    private:
    	int x;
    public:
    	void setX(int i)
    	{
    		x=i;
    	}
    	void show()
    	{
    		cout<<"x="<<x<<endl;
    	}
    };
    class Drevid: public Base  
    {
    public:
    	  void show1()     //添加成员函数
    	{
    		cout<<"LWT love Lwt"<<endl;
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	d.setX(20);   //  改变成员   
    	d.show();	//继承成员							
    	d.show1();                           
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    2.覆盖改变成员

    #include 
    using namespace std;
    class Base                                      //基类
    {
    private:
    	int x;
    public:
    	void setX(int i)
    	{
    		x=i;
    	}
    	void show()
    	{
    		cout<<"x="<<x<<endl;
    	}
    };
    class Drevid: public Base                
    public:
    	void show1()
    	{
    		cout<<"我喜欢!"<<endl;
    	}
    	void show()                           
    	{
    		cout<<"喜欢我!"<<endl;
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	d.setX(20);                            
    	d.show();	//覆盖							
    	d.show1();
    	return 0;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    (五)、继承方式和派生类的访问权限

    (1).公有继承(公私保变公私保)

    最常见的继承方式,基类的public成员仍然作为派生类的public成员;基类中的privat成员被隐藏(使得派生类内部也变得不可以直接访问私有成员)。虽然不能够直接访问基类的private成员,但可通过从基类的公有成员访问派生类的对象可以访问基类中的非private成员;

    派生类的对象只能访问基类中的public成员

    (2).保护继承(公私保全变保)

    派生类的内部,基类的公有成员和保护成员均作为派生类的保护成员,派生类的成员可以直接访问它们,而派生类的成员无法访问基类的私有成员。

    保护继承时基类中各成员属性均变为protected,并且基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;派生类的对象不能访问基类中的任何的成员

    1.本类内部: 可以访问基类的public/private
    2.本类的对象: 不能访问基类的任何成员
    3.本类的派生类内部: 可以访问基类的public/private
    4.本类的派生类对象: 不能访问基类的任何成员

    派生类的外部:派生类的成员和派生类的对象均无法访问基类的全部成员

    如果基类只进行了一次派生,则保护继承和私有继承的功能完全相同,但保护继承可以进一步派生,而私有继承则不可以.

    (3).私有继承:(公私保变私)

    基类中的private被隐藏,在派生类的内部,基类的公有成员和保护成员作为派生类的私有成员,派生类的成员可以直接访问基类中(公有和保护),而派生类的对象无法访问基类的任何成员

    私有继承之后,全部基类成员在派生类中都成为了私有成员或不可访问的成员,进一步派生后,将再也无法直接访问

    派生类对象不能访问基类中的任何的成员函数

    (六)各种实列

    1.【公有继承下派生类通过公有成员访问私有成员】

    #include 
    using namespace std;
    class Base                                      
    {
    private:
    	int x;
    public:
    	void setX(int i)
    	{
    		x=i;
    	}
    	void show()
    	{
    		cout<<"x="<<x<<endl;
    	}
    	int getX()      //共有返回私有
    	{
    		return x;
    	}
    };
    class Drevid: public Base                  
    {
    public:
    	void display()
    	{
    		cout<<"x="<< getX()<<endl;      //访问基类中的私有
    	}	
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	d.setX(20);
    	d.display();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.【公有继承下派生类通过公有成员访问保护成员】

    #include 
    using namespace std;
    class Base
    {
    protected:     //保护
    	int x;
    public:
    	void setX(int i)
    	{
    		x = i;
    	}
    	void show()
    	{
    		cout << "x=" << x << endl;
    	}
    	int getX()      //共有返回保护
    	{
    		return x;
    	}
    };
    class Drevid : public Base
    {
    public:
    	void display()
    	{
    		cout << "x=" << getX() << endl;      //访问基类中的保护
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	d.setX(20);
    	d.display();   
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    3.【私有继承下类外不能访问基类的所有成员】

    #include 													
    using namespace std;
    class Base                                      
    {
    private:
    	int y;
    protected:
    	int x;
    public:
    	void setX(int i)
    	{
    		x=i;
    	}
    	void show()
    	{
    		cout<<"x="<<x<<endl;
    	}
    };
    class Drevid: private Base               //私有继承访问                 
    {
    public:
    		void show1()
    
    		{
    			cout<<"我的名字:"<<endl;
    		}
    };
    int main()
    {
    	Base b;
    	b.setX(10);							
    	b.show();						     
    	Drevid d;
    //	d.setX(20);   //会报错,因为现在基类的公有成员被私有成员访问,所以...
    //	d.show();     //会报错,因为现在基类的公有成员被私有成员访问,所以...                     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    4.【私有继承下访问基类的私有数据成员】

    #include 													
    using namespace std;
    class Base
    {
    private:
    	int y;
    protected:
    	int x;
    public:
    	void setY()
    	{
    		cout << "结果为:y=" << 10 << endl;
    	}
    	void setX(int i)
    	{
    		x = i;
    	}
    	void show()
    	{
    		cout << "x=" << x << endl;
    	}
    	int getX()
    	{
    		return x;
    	}
    };
    class Drevid : private Base
    {
    public:
    	void show1()
    	{
    		setY();                      //会变成私有
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	d.show1();    //派生类可以访问派生类
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    5.【私有继承下进一步派生】

    
    #include 													
    using namespace std;
    class Base                                      
    {
    private:
    	int y;
    protected:
    	int x;
    	void setY()
    	{
    		y=10;
    	 }
    public:
    	void setX(int i)
    	{
    		x=i;
    	}
    	void show()
    	{
    		cout<<"x="<<x<<endl;
    	}
    	int getX()
    	{
    		return x;
    	}
    };
    class Drevid: private Base                     
    {
    public:
    	void show1()
    	{
    		setY();                      //基类中的保护会员变成私有成员
    	}	
    };
    class DDrevid: public Drevid          //用公有继承的方式进一步派生后
    {
    public:
    	void f()
    	{
    	//	setY();        报错             //进一步派生后,仍然还是私有成员
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    //	d.setY();        报错     //这个已经变成派生类的私有成员,在类外不能访问.
    	d.show1();   
    	DDrevid d1;
    	d1.f();           //进一步派生后,仍然无法访问
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    6.【保护继承进一步派生】

    #include 													
    using namespace std;
    class Base
    {
    private:
    	int y;
    protected:
    	int x;
    	void setY()
    	{
    		y = 10;
    	}
    public:
    	void setX(int i)
    	{
    		x = i;
    	}
    	void show()
    	{
    		cout << "x=" << x << endl;
    	}
    	int getX()
    	{
    		return x;
    	}
    };
    class Drevid : protected Base
    {
    public:
    	void show1()
    	{
    		setY();                      //基类中的保护成员会变成保护成员
    	}
    };
    class DDrevid : public Drevid
    {
    public:
    	void f()
    	{
    		setY();                     //进一步派生后,公有继承下仍然是保护成员
    	}
    };
    int main()
    {
    	Base b;
    	b.setX(10);
    	b.show();
    	Drevid d;
    	//	d.setY();         报错    //这个已经变成派生类的保护成员,在类外不能访问.
    	d.show1();
    	DDrevid d1;
    	d1.f();              //可以访问
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    (七)、派生类的构造函数

    1.什么是派生类的构造函数:

    1.派生类的数据成员既包括从基类继承的数据成员,也包括派生类新增的数据成员,甚至还可能包括派生类内定义的内嵌成员对象.

    2.派生类构造函数在对派生类对象进行初始化时需要对基类数据成员,新增数据成员和内嵌对象成员进行初始化.

    3.派生类会继承除基类构造函数外的所有基类成员,也就是说,(派生类是不能继承基类的构造函数的!!!)

    4.在定义派生类的构造函数时除了对自己的数据成员进行初始化外,还必须借助派生类的构造函数,调用基类的构造函数,从而结组基类的构造函数,从而借助基类的构造函数,来初始化从基类继承的数据成员.

    5.如果派生类拥有对象成员时,派生类的构造函数还拥有对象成员所属类构造函数,来初始化这个对象成员.

    2.派生类构造函数的格式(构造函数先基再派,析构函数先派后基)

    (2).派生类的构造函数的定义格式:

    派生类名::派生类名(): 类名(),内嵌对象成员名1…
    {
    派生类新增成员的初始化
    }

    (3).当基类中没有显示定义构造函数时,派生类的构造函数定义可以省略,系统采用默认的构造函数

    (4).当基类定义了具有形参的构造函数时,派生类很可能也需要显示定义构造函数,提供将参数传递给基类构造函数的途径,使基类对象在初始化时可以获取相关数据,在某些情况下,派生类构造函数的函数体可能为空,仅起参数产地及调用基类与内嵌对象构造函数的作用

    (5).派生类定义构造函数会自动调用基类构造函数

    3.实列(派生类构造函数的初始化)

    代码展示:

    #include 
    using namespace std;
    class Inner
    {
    private:
    	int y;
    public:
    	Inner(int b)
    	{
    		y=b;
    		cout<<"inner的构造函数:"<<y<<endl;
    	}
    };
    class Base
    {
    protected:
    	int x;
    public:
    	Base(int a)
    	{
    		x=a;
    		cout<<"基类的构造函数:"<<x<<endl;
    	}
    };
    class Derived: public Base
    {
    private:
    	Inner i;
    	int z;
    public:
    	Derived(int a,int b,int c):Base(a),i(b)									//派生类构造函数,有内嵌,加派生类新增
    	{
    		z=c;
    		cout<<"派生类的构造函数:"<<z<<endl;
    	}
    };
    int main()
    {
    	Base b(100);
    	cout<<"*************************************"<<endl;
    	Derived d(10,20,30);                                                       //+++++++++++++++
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    在这里插入图片描述
    如有不解,随时支持私聊!!!!!

  • 相关阅读:
    计算机毕业论文基于Python实现的仓库库存管理系统进销存储系统
    领英辅助工具领英精灵分组功能解析
    Java内部类(成员内部类、静态内部类、局部内部类、局部内部类)
    JAVA内存模型与JVM内存结构
    Go语言中获取IP
    如何截取视频中的一段视频?分享几种视频分割方法
    Go Zero微服务个人探究之路(十六)回顾api服务和rpc服务的本质
    项目环境配置
    【Java】List、Set、数据结构、Collections
    angular记录
  • 原文地址:https://blog.csdn.net/qq_69683957/article/details/126405825