[C++]类的继承与派生

继承性是面向对象程序设计的第二大特性,它允许在既有类的基础上创建新类,新类可以继承既有类的数据成员和成员函数,可以添加自己特有的数据成员和成员函数,还可以对既有类中的成员函数重新定义。利用类的继承和派生实现了更高层次的代码可重用性,符合现代软件开发的思想。

C++语言同时支持单一继承和多重继承。单一继承是指派生类只从一个基类继承而来;相应的,多重继承指派生类同时从两个或更多的基类继承而来。java只支持单一继承。

一. 派生类

派生类的定义格式如下:

class <派生类名>:[继承方式]<基类名1>

[,[继承方式]<基类名2>,...,[继承方式]<基类名n>]

{

<派生类新增的数据成员和成员函数定义>

};

说明:

(1)定义派生类关键字可以是class或者是struct,两者区别是:用class定义派生类,默认的继承方式是private,用struct定义派生类,默认的继承方式为public。新增加的成员默认属性也是class对应private属性,struct对应public属性。

(2)基类不能被派生类继承的两类函数是构造函数和析构函数。

二. 3种继承方式下基类成员在派生类中的访问属性

用下面的代码简单理解一下:

#include "stdafx.h"
#include<iostream>
using namespace std;

class Base
{
private:
    int priData;
protected:
    int proData;
public:
    int pubData;
};

class D1:private Base//私有继承
{
    void f1()
    {
        //priData=1;//基类private成员在派生类中不可直接访问
        proData=2;//基类的protected成员在派生类中为private访问属性
        pubData=3;//基类的public成员在派生类中为private访问属性
    }
};

class D2:protected Base//保护继承
{
    void f2()
    {
        //priData=1;//基类private成员在派生类中不可直接访问
        proData=2;//基类的protected成员在派生类中为protected访问属性
        pubData=3;//基类的public成员在派生类中为protected访问属性
    }
};

class D3:public Base//公有继承
{
    void f3()
    {
        //priData=1;//基类private成员在派生类中不可直接访问
        proData=2;//基类的protected成员在派生类中为protected访问属性
        pubData=3;//基类的public成员在派生类中为public访问属性
    }
};

int main()
{
    Base obj;
    //obj.priData=1;//对象不可访问Base类中private成员
    //obj.proData=2;//对象不可访问Base类中protected成员
    obj.pubData=3;
    D1 objD1;
    //objD1.pubData=3;//private属性,不可访问
    D2 objD2;
    //objD2.pubData=3;//protected属性,不可访问
    D3 objD3;
    objD3.pubData=3;//public属性,可以访问
    return 0;
}

基类的private成员函数虽然在派生类的成员函数中不可直接访问,但派生类的成员函数可以通过调用基类被继承的函数来间接访问这些成员。如果基类的函数被继承后在派生类中仍为public成员,则可以通过派生类对象直接调用。
      先来看一下类成员的访问属性及作用:

访问属性 作用
private 只允许该类的成员函数及友元函数访问,不能被其他函数访问
protected 既允许该类的成员函数及友元函数访问,也允许其派生类的成员函数访问
public 既允许该类的成员函数访问,也允许类外部的其他函数访问

好了,继续通过代码来理解:

#include "stdafx.h"
#include<iostream>
using namespace std;

class Base
{
private:
    int priData;
protected:
    int proData;
public:
    int pubData;
//在类的定义中不能对数据成员进行初始化
    void SetData()//为基类中的数据成员赋值
    {
        priData=100;
        proData=200;
        pubData=300;
    }
    void Print()
    {
        cout<<"priData="<<priData<<endl;
        cout<<"proData="<<proData<<endl;
        cout<<"pubData="<<pubData<<endl;
    }
};

class Derived:public Base
{
public:
    void ChangeData()
    {
        SetData();
        proData=12;//在派生类的成员函数类可以访问基类的非私有成员
    }
};

int main()
{
    Base b;
    b.SetData();
    b.Print();

    Derived d1;
    d1.ChangeData();
    d1.pubData=13;
    d1.Print();

    return 0;
}

程序运行结果如下:

三. 派生类的构造函数和析构函数

在定义一个派生类的对象时,在派生类中新增加的数据成员当然用派生类的构造函数初始化,但是对于从基类继承来的数据成员的初始化工作就必须由基类的构造函数完成,这就需要在派生类的构造函数中完成对基类构造函数的调用。同样,派生类的析构函数值能完成派生类中新增加数据成员的扫尾、清理工作,而从基类继承来的数据成员的扫尾工作也应有基类的析构函数完成。由于析构函数不能带参数,因此派生类的析构函数默认直接调用了基类的析构函数。

派生类构造函数定义格式如下:

<派生类名>(<总形式参数表>):<基类名1>(<参数表1>),

<基类名2>(<参数表2>),[...,<基类名n>(<参数表n>),其他初始化项>]

{

[<派生类自身数据成员的初始化>]

}

说明:

(1)总形式表给出派生类构造函数中所有的形式参数,作为调用基类带参构造函数的实际参数以及初始化本类数据成员的参数;

(2)一般情况下,基类名后面的参数表中的实际参数来自前面派生类构造函数形式参数总表,当然也可能是与前面形式参数无关的常量;

(3)在多层次继承中,每一个派生类只需要负责向直接基类的构造函数提供参数;如果一个基类有多个派生类,则每个派生类都要负责向该积累的构造函数提供参数。

1.单一继承

#include"stdafx.h"
#include<iostream>
using namespace std;

class Other
{
public:
    Other()
    {
        cout<<"constructing Other class"<<endl;
    }
    ~Other()
    {
        cout<<"destructing Other class"<<endl;
    }
};

class Base
{
public:
    Base()
    {
        cout<<"constructing Base class"<<endl;
    }
    ~Base()
    {
        cout<<"destructing Base class"<<endl;
    }
};

class Derive:public Base
{
private:
    Other ot;
public:
    Derive()
    {
        cout<<"constructing Derive class"<<endl;
    }
    ~Derive()
    {
        cout<<"destructing Derive class"<<endl;
    }
};

int main()
{
    Derive d;

    return 0;
}

程序运行结果如下:

可以看到定义派生类对象时,构造函数的调用顺序:

a.先调用基类的构造函数

b.然后调用派生类对象成员所属类的构造函数(如果有对象成员)

c.最后调用派生类的构造函数

析构函数的调用顺序正好与构造函数调用顺序相反。

2.多重继承

#include"stdafx.h"
#include<iostream>
using namespace std;

class Grand
{
    int g;
public:
    Grand(int n):g(n)
    {
        cout<<"Constructor of class Grand g="<<g<<endl;
    }
    ~Grand()
    {
        cout<<"Destructor of class Grand"<<endl;
    }
};

class Father:public Grand
{
    int f;
public:
    Father(int n1,int n2):Grand(n2),f(n1)
    {
        cout<<"Constructor of class Father f="<<f<<endl;
    }
    ~Father()
    {
        cout<<"Destructor of class Father"<<endl;
    }
};

class Mother
{
    int m;
public:
    Mother(int n):m(n)
    {
        cout<<"Constructor of class Mother m="<<m<<endl;
    }
    ~Mother()
    {
        cout<<"Destructor of class Mother"<<endl;
    }
};

class Son:public Father,public Mother
{
    int s;
public:
    Son(int n1,int n2,int n3,int n4):Mother(n2),Father(n3,n4),s(n1)
    {
        cout<<"Constructor of class Son s="<<s<<endl;
    }
    ~Son()
    {
        cout<<"Destructor of class Son"<<endl;
    }
};

int main()
{
    Son s(1,2,3,4);
    return 0;
}

程序运行结果如下:

可以看到,与单一继承不同的是:在多重继承中,派生类有多个平行的基类,这些处于同一层次的基类构造函数的调用顺序,取决于声明派生类时所指定的各个基类的顺序,而与派生类构造函数的成员初始化列表中调用基类构造函数的顺序无关。

时间: 2024-12-21 07:52:41

[C++]类的继承与派生的相关文章

模块的封装之C语言类的继承和派生

[交流][微知识]模块的封装(二):C语言的继承和派生 在模块的封装(一):C语言的封装中,我们介绍了如何使用C语言的结构体来实现一个类的封装,并通过掩码结构体的方式实 现了类成员的保护.这一部分,我们将 在此的基础上介绍C语言类的继承和派生.其实继承和派生是一个动作的两种不同角度的表达 .当我们继承了一个基类而创造了一个新类时,派生的概念就诞生了.派生当然是从基类派生的.派生出来的类当然是继承了基类的 东西.继承和派生不是一对好基友,他们根本就是一个动作的两种不同的说法,强调动作的起始点的时候

黑马程序员-----类的继承和派生概念

------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ----- 第一讲 类的继承和派生概念 本小节知识点: 1.[理解]什么是继承? 2.[掌握]类的继承和派生概念 1.什么是继承? 2.OC中的继承与派生 1 #import <Foundation/Foundation.h> 2 3 @in

Day17:类的继承、派生、组合和接口

一.类的继承.派生和组合 继承是一种创建新类的方式,在Python中,新类可以继承一个或多个父类,父类又可称为基类或者超类,新建的类称为派生类或子类. 在Python3中,所有类都默认继承object,都是新式类.在Python2中,有经典类和新式类.没有继承object类以及object的子类的类都是经典类. 1.继承 Python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass clas

类的继承和派生

一.类的继承.派生和组合 继承是一种创建新类的方式,在Python中,新类可以继承一个或多个父类,父类又可称为基类或者超类,新建的类称为派生类或子类. 在Python3中,所有类都默认继承object,都是新式类.在Python2中,有经典类和新式类.没有继承object类以及object的子类的类都是经典类. 1.继承 Python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass clas

Day29:类的继承、派生、组合和接口

一.类的继承.派生和组合 继承是一种创建新类的方式,在Python中,新类可以继承一个或多个父类,父类又可称为基类或者超类,新建的类称为派生类或子类. 在Python3中,所有类都默认继承object,都是新式类.在Python2中,有经典类和新式类.没有继承object类以及object的子类的类都是经典类. 1.继承 Python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass clas

09--c++ 类的继承与派生

c++ 类的继承与派生 一.基本概念 1.类的继承,是新的类从已有类那里得到已有的特性.或从已有类产生新类的过程就是类的派生.原有的类称为基类或父类,产生的新类称为派生类或子类. 2.派生类的声明: class 派生类名:继承方式 基类名1, 继承方式 基类名2,...,继承方式 基类名n { 派生类成员声明: }; 3.一个派生类可以同时有多个基类,这种情况称为多重继承,派生类只有一个基类,称为单继承.直接派生,间接派生. 4.继承方式规定了如何访问基类继承的成员.继承方式有public, p

实验4 类的继承、派生和多态(1)

实验目的 1. 理解类的继承和派生机制 2. 掌握派生类的定义和使用 3. 理解和掌握派生类成员的标识和访问中同名覆盖原则.二元作用域分辨符和虚基类的用法 4. 掌握派生类构造函数和析构函数的定义及调用次序 5. 理解运算符重载的目的,掌握运算符重载函数的编写方法 实验准备 1. 类的继承和派生 引入继承和派生机制的目的 基本概念:继承.派生.基类.直接基类.间接基类 .派生类 语法 派生类定义的语法格式(单重继承和多重继承) 派生类构造函数及其初始化列表书写形式 派生类成员的标识与访问 同名覆

c++实验四 类的继承、派生和多态

实验目的 1. 理解类的继承和派生机制 2. 掌握派生类的定义和使用 3. 理解和掌握派生类成员的标识和访问中同名覆盖原则.二元作用域分辨符和虚基类的用法 4. 掌握派生类构造函数和析构函数的定义及调用次序 5. 理解运算符重载的目的,掌握运算符重载函数的编写方法 实验内容 一.ElectricCar类 #ifndef BATTERY_H #define BATTERY_H class Battery { public: Battery(int nb = 70); int showbattery

类的继承与派生

继承与派生 在教材中给出的对类的继承和派生的解释: "类的继承,是新的类从已有类那里得到已有的特性." "从已有的类产生新类的过程就是类的派生." 新的类是基类的派生类,新的类从基类处得到已有的特性. 一.继承与派生举例 新的类是基类的派生类,新的类从基类处得到已有的特性. 例1.写一个类student,再写一个Student类的派生类Undergraduate. 代码: #define _CRT_SECURE_NOWARNINGS #include<iost