[C++] Class inheritance and derivation

[C++] Class inheritance and derivation

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

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

1. Derived class

The definition format of the derived class is as follows:

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

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

  {

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

  };

Description:

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

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

2. Access attributes of base class members in derived classes under three inheritance methods

Insert picture description here
Use the following code to understand briefly:

#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;
}

Although the private member functions of the base class are not directly accessible in the member functions of the derived class, the member functions of the derived class can indirectly access these members by calling the inherited functions of the base class. If the function of the base class is still a public member in the derived class after being inherited, it can be called directly through the derived class object.
First look at the access attributes and functions of class members:

Access to attribute function private only allows access to member functions and friend functions of this class, and cannot be accessed by other functions. protected Allows access to member functions and friend functions of this class as well as member functions of its derived classes. Public allows both the class The member function access, also allows other functions outside the class to access
Well, continue to understand through the code:

#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;
}
  程序运行结果如下:

Insert picture description here

Three. The constructor and destructor of the derived class

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

The definition format of the derived class constructor is as follows:
<derived class name> (<total formal parameter table>): <base class name 1> (<parameter table 1>),

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

   {

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

    }

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

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

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

1. Single inheritance

#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;
}

The results of the program are as follows:
Insert picture description here

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

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

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

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

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

2. Multiple inheritance

#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;
}

The results of the program are as follows:
Insert picture description here

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

Guess you like

Origin blog.csdn.net/wmy0536/article/details/106006006
Recommended