C++ 继承与派生

为什么要使用继承:
•最高层(基类):是最普遍、最一般的
•低层(派生类):比它的上一层更具体,并且含有高层的特性(继承),同时也与高层有细微的不同
•继承性是程序设计中一个非常有用的、有力的特性,它可以让程序员在既有类的基础上,通过增加少量代码或修改少量代码的方法得到新的类,从而较好地解决了代码重用的问题

一般格式:

class 派生类名:派生方式基类名{
    //派生类新增的数据成员和成员函数
};

派生分类:
?在声明派生类时,根据“派生方式”所写的关键字不同可以分为三种派生方式:?用public关键字的为公有派生方式?用private关键字的为私有派生方式?用protected关键字的为保护派生方式
?从继承源上分:?单继承:指每个派生类只直接继承了一个基类的特征?多继承:指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基类的特征

class employee:publicperson{
//…
};
•基类中的私有成员–>派生类中不可访问
•基类中的公有成员–>派生类中是公有的

//公有派生
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{     //基类
private:
    int x;
public:
    int y;
    void setXY(int n,int m){
        x = n;
        y = m;
    }
    void showXY(){
        cout<<x<<','<<y<<endl;
    }
};

class Derived:public Base{      //公有派生类
private:
    int z;
public:
    void setZ(int m){ 
        z = m;
    }
    /*void show(){
        cout<<x<<','<<y<<','<<z<<endl;
    }*/
};


int main()
{
    Derived obj;
    obj.y = 3;
    obj.setXY(10,20);       //ok
    obj.setZ(30);           //ok
    obj.showXY();           //ok
    //obj.show();               //okx
    return 0;
}

?私有派生
class employee:privateperson{
//…
};

•基类中的私有成员–>派生类中不能访问
•基类中的公有成员–>派生类中是私有的

//私有继承
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class base{     //基类
private:
    int x;
    int y;
public:
    void setXY(int n,int m){
        x = n;
        y = m;
    }
    void showXY(){
        cout<<x<<','<<y<<endl;
    }
};

class derived:private base{     //私有派生类
private:
    int z;
public:
    void set(int n,int m,int r){  
        setXY(n,m);
        z = r;
    }
    void show(){ 
        cout<<z<<endl;
        showXY();
        //cout<<x<<','<<y<<','<<z<<endl;        //?
    }
};

int main()
{
    derived obj;
//  obj.setXY(10,20);                       //?
    obj.set(10,20,30);
    obj.show();
    return 0;
}

?私有成员在派生类中是无权直接访问的,只能通过调用基类中的公有成员函数的方式实现
?一定要直接访问基类中的私有成员,可以把这些成员声明为保护成员rotected。一般格式:

class 类名{
    private:
        私有成员
    protected:
        保护成员
    public:
        公有成员
};
//不涉及派生时,保护成员与私有成员的地位完全一致。
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Samp{
private:
    int a;
protected:  
    int b;
public: 
    int c;
    Samp(int n,int m){
        a = n;
        b = m;
    }
    int getA(){
        return a;
    }
    int getB(){
        return b;
    }
};

int main()
{   
    Samp obj(20,30);
    //obj.a = 11;       //Error,私有成员
    //obj.b = 22;       //Error,保护成员
    obj.c = 33;     //Ok
    cout<<obj.getA()<<' '<<obj.getB()<<endl;    //Ok
    return 0;
}
//基类中的保护成员在公有派生的派生类中仍是保护的
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{
protected:
    int a, b;
public:
    void setAB(int n,int m){
        a = n;
        b = m;
    }
};

class Derive:public Base{
private:
    int c;
public: 
    void setC(int n){
        c = n;
    }
    void showABC(){
        cout<<a<<' '<<b<<' '<<c<<endl; 
    }
};

int main()
{   
    Derive obj;
    //obj.a = 3;
    obj.setAB(2,4);
    obj.setC(3);
    obj.showABC();
    return 0;
}
//构造函数与析构函数的执行顺序
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{
protected:
    int a;
public:
    void setA(int sa){
        a = sa;
    }
};


class Derive1:private Base{
protected:
    int b;
public:
    void setB(int sb){
        b = sb;
    }
};

class Derive2:public Derive1{
private:
    int c;
public:
    void setC(int sc){
        c = sc;
    }
    void show(){
        cout<<a<<' '<<b<<' '<<c<<endl;
        //cout<<b<<' '<<c<<endl;
    }
};

int main()
{
    Base op1;
    op1.setA(1);

    Derive1 op2;
    op2.setB(2);

    Derive2 op3;
    op3.setC(3);
    op3.setB(4);

    op3.show();
    return 0;
}

•基类中的私有成员–>派生类中不能访问
•基类中的公有成员–>派生类中是保护的保护派生

class employee:protectedperson{
    //…
};
//保护派生
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{     //基类
private:
    int x;
public:
    int y;
    void setXY(int n,int m){
        x = n;
        y = m;
    }
    void showXY(){
        cout<<x<<','<<y<<endl;
    }
};

class Derived:protected Base{       //保护派生类
private:
    int z;
public:
    void setXYZ(int a,int b,int m){ 
        setXY(a,b);
        z = m;
    }
    void show(){
        showXY();
        cout<<z<<endl;
    }
};

int main()
{
    Derived obj;
    //obj.y = 3;            //error
    //obj.setXY(10,20);     //error
    obj.setXYZ(10,20,30);           //ok
//  obj.showXY();           //error
    obj.show();             //okx
    return 0;
}

这里写图片描述

��多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。
��多继承下派生类的定义格式如下:

class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{
    <派生类类体>
};

其中,<继承方式1>,<继承方式2>,…是三种继承方式:public、private、protected之一
注意:当使用多继承时要注意避免发生二义性

class A{
    public:
    //……
};
class B{
    public:
    //……
};
class C:publicA,publicB{
    ……
};
在定义如下时:
C c1;
c1.print(); //error

解决方法是:c1.A::print();//调用A的或者c1.B::print();//调用B的..在C公有继承A和B,当A和B都公有继承D时,这使得A和B都具有D的公有部分,在C中使用D的公有部分时,编译器就会不确定是调用A的还是调用B的而出现错误

1 派生类构造函数和析构函数的执行顺序
..派生类构造函数的执行顺序:
基类构造函数 —–> 派生类构造函数
..派生类析构函数的执行顺序:
派生类构造函数 —–> 基类构造函数

//派生类的构造函数与析构函数的执行顺序
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{
public:
    Base(){
        cout<<"Construction base class.\n";//1
    }
    ~Base(){
        cout<<"Destruction base class.\n";//4
    }
};

class Derive:public Base{
public:
    Derive(){
        cout<<"Construction derived class.\n";//2
    }
    ~Derive(){
        cout<<"Destruction derived class.\n";//3
    }
};

int main()
{
    Derive op;
    return 0;
}

��当基类的构造函数没有参数(或全部默认值),或没有显示定义构造函数时,那么派生类可以不向基类传递参数,可以不定义构造函数
��当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供把参数传递给基类构造函数的途径
•派生类构造函数的一般格式:
派生类构造函数名(参数表0):基类构造函数名(参数表1){
//…
}

•当派生类中含有对象成员时,其构造函数的一般形式为:
派生类构造函数名(参数表0):基类构造函数名(参数表1),对象成员名1(参数表2),…,对象成员名n(参数表n+1){
//…
}
在定义派生类对象时,构造函数与析构函数的执行顺序为:
..派生类构造函数的执行顺序:
基类构造函数 —–>对象成员 —–> 派生类构造函数
..派生类析构函数的执行顺序:
派生类构造函数 —–> 对象成员 —–> 基类构造函数

//构造函数与析构函数的执行顺序
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class Base{
private:
    int x;
public:
    Base(int i){ 
        x = i;
        cout<<"构造base类, x="<<x<<endl;
    }
    ~Base(){ 
        cout<<"析构base类, x="<<x<<endl;
    }
    void show(){ 
        cout<<"x="<<x<<endl;
    }
};


class Derive:public Base{
private:
    int y;
    Base d;
public:
    Derive(int i,int j,int k):Base(i),d(j){ 
        y = k;
        cout<<"构造derived类, y="<<y<<endl;
    }
    ~Derive(){ 
        cout<<"析构derived类, y="<<y<<endl;
    }
};

int main()
{
    Derive obj(1,2,3);
    obj.show();
    return 0;
}

输出结果:
构造base类,x=1
构造base类,x=2
构造derived类,y=3
x=1
析构derived类,y=3
析构base类,x=2
析构base类,x=1

说明
:•如果派生类的基类也是一个派生类,则每个派生类只需负责其直接基类的构造,依次上溯
•由于析构函数是不带参数的,在派生类中是否要定义析构函数与它所属的基类无关,故基类的析构函数不会因为派生类没有析构函数而得不到执行,它们各自是独立的

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值