第8篇:C++ 类多继承(后篇)

作者: 铁甲万能狗 | 来源:发表于2019-11-08 17:26 被阅读0次

我们从上篇已经了解到多继承的特性,同时在很多场合中他的负面作用大于它的正面作用。这里是一个简化后的棱形问题,有时,我们不得不使用这样的继承模式.如下图所示

ss17.png
为了避免在初始化过程中,顶层的父类重复构造,那么C++有个virtual关键字,在本示例中,我们只需给BlackMagic类和WhiteMagic类的继承列表中分别用virtual关键字修饰父类Magic
#include <string>
#include <iostream>

using namespace std;


class Magic{
public:
     Magic(){cout<<"初始化 - Magic实例"<<endl;}
     ~Magic(){cout<<"内存释放 - Magic实例"<<endl;}
};

class BlackMagic:virtual public Magic{
public:
  BlackMagic(){cout<<"初始化-黑魔法师"<<endl;}
  ~BlackMagic(){cout<<"内存回收-黑魔法师"<<endl;}
  ....
};


class WhiteMagic:virtual public Magic{
public:
  WhiteMagic(){cout<<"初始化-白魔法师"<<endl;}
  ~WhiteMagic(){cout<<"内存回收-白魔法师"<<endl;}
  ....
};

class Role:public WhiteMagic,public BlackMagic{
  string d_name;
  size_t d_hp;
  
public:
    Role(const string& name,
         size_t hp):d_name(name),d_hp(hp){
        cout<<"角色初始化 -"<<d_name
        <<"HP:"<<d_hp<<endl;
    }
    ~Role(){cout<<"内存回收-游戏角色"<<endl;}
    
    size_t attck(){
        cout<<d_name<<"施加attack方法"<<endl;
    }
    
    size_t magic(){
        cout<<d_name<<"施加magic方法"<<endl;
    }
};

int main(void){
    Role yuna=Role("Yuna",1500);
    
    yuna.fira();
    yuna.holy();
    return 0;
}

程序输出

virtual关键字的副作用,即使父类显式调用了自定义的构造函数,默认情况下也只会调用父类的默认构造函数。那有方法可以显示调用父类的自定义构造函数吗?请继续往下看,这也是本文的重点。

多继承链中调用自定义构造函数

我们对上文的示例代码做一些扩展,Role的继承链中前端的所有父类都各自增加自己的自定义构造函数。

继承链中的子类对上一级父类的自定义构造函数的调用的方法:就是在当前子类构造函数的初始化参数列表中显式调用父类的构造函数,通常,不允许直接调用父类中的构造函数,而必须通过父类进行调用。 仅在使用“virtual”关键字时才允许使用。一般形式如下图所示

继承链中没virtual关键字的情况下,在调用自定义构造函数需要在子类构造函数的初始化参数列表以这样格式"父类名::构造函数原型"显式指定。

示例代码

class Magic{
    size_t d_mp;
    string d_name;
public:
    Magic(){cout<<"初始化 - Magic实例"<<endl;}
    //父类中构造函数
    Magic(const string& name,size_t mp)
    :
    d_name(name),
    d_mp(mp)
    {
        cout<<"魔法技能:"<<d_name<<"初始MP "<<d_mp<<endl;
    }
     ~Magic(){cout<<"内存释放 - Magic实例"<<endl;}
};

class BlackMagic:virtual public Magic{
public:
  BlackMagic(){cout<<"初始化-黑魔法师"<<endl;}
  //父类中构造函数
  BlackMagic(size_t mp):Magic("黑魔法师",mp){
      cout<<"构造函数:BlackMagic("<<mp<<")初始化"<<endl;
  }
  
  ~BlackMagic(){cout<<"内存回收-黑魔法师"<<endl;}
  size_t fira(){
    cout<<"fire初级火魔法"<<endl;
  }
  ...
};

class WhiteMagic:virtual public Magic{
public:
  WhiteMagic(){cout<<"初始化-白魔法师"<<endl;}
 //父类中构造函数
  WhiteMagic(size_t mp):Magic("白魔法师",mp){
      cout<<"构造函数:WhiteMagic("<<mp<<")初始化"<<endl;
  }

  ~WhiteMagic(){cout<<"内存回收-白魔法师"<<endl;}
  size_t haste(){
    cout<<"haste魔法"<<endl;
  }
  ...
};

class Role:public WhiteMagic,public BlackMagic{
  string d_name;
  size_t d_hp;
  
public:
    Role(const string& name,
        size_t hp):d_name(name),d_hp(hp){
        cout<<"角色初始化 -"<<d_name
        <<"HP:"<<d_hp<<endl;
    }
    
    Role(const string& name,size_t hp,size_t mp)
    :WhiteMagic(mp),BlackMagic(mp),d_name(name),d_hp(hp)
    {
        cout<<"角色初始化 - "<<d_name<<
        "HP:"<<d_hp<<" MP:"<<mp<<endl;
    }
    
    ~Role(){cout<<"内存回收-游戏角色"<<endl;}
};

int main(void){
    Role yuna=Role("Yuna",1500,300);
    return 0;
}

程序输出如下:

总结:

关于C++的类继承的部分,我们更多地阐述了一个多继承的副作用,尤其在棱形问题方面在内存分配方面会造成资源浪费,内存回收时,如果继承链中的类内部存在堆内存分配,因为重复调用父类的解构函数,就可能存在内存泄漏的风险。虽然可以在棱形的继承链中的子类使用virtual关键修正这一问题。但virtual关键字也带来一些副作用,我们也逐一阐述了在多继承中如何显式地调用自定义构造函数。

后记

我们在本篇引入了虚拟函数这个概念。这是在C++运行时(Run-Time)多态中一个非常重要的特征。之前写过的很多的文章介绍过函数重载和operator 函数重载。它们属于编译时多态(Compile-Time)。

相关文章

  • 第8篇:C++ 类多继承(后篇)

    我们从上篇已经了解到多继承的特性,同时在很多场合中他的负面作用大于它的正面作用。这里是一个简化后的棱形问题,有时,...

  • Java学习笔记三:继承、封装、多态

    一、继承 (1)继承知识点 父类也称作超类、基类、派生类等。 Java中只有单继承,没有像C++那样的多继承。多继...

  • 17-多继承

    多继承 C++允许一个类可以有多个父类(不建议使用,会增加程序的复杂度) 关于C++ 的多继承,定义了以下几个类,...

  • Java--继承使用要点

    1.父类也称作超类、基类、派生类等。2.Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承...

  • JNI基础 -- C++基础知识(继承多态,虚函数 )

    继承 在Java中类的继承只能是单继承,但是在C++中可以多继承。继承是通过一个冒号表示的,如下: C++中的继承...

  • 2020-02-17-C++虚继承机制

    C++ 中出现多继承,当多继承就会出现 两个父类的复制,这样就出现了虚继承机制。 A 继承 ZB继承 ZC 继承 ...

  • 第8篇:C++ 类继承(前篇)

    如果你之前学过一些高层语言,Java或者C#的类继承相对比较简单,到了C++的类继承较为复杂的,因为C++支持多继...

  • [C++之旅] 18 公有继承、保护继承和私有继承

    [C++之旅] 18 公有继承、保护继承和私有继承 继承 继承的类称为派生类或子类,被继承的类称为基类或父类。继承...

  • Java 基础 - 继承

    参考 C++多继承有什么坏处,Java的接口为什么可以摈弃这些坏处?C++多继承(钻石继承)的问题和解决C++继承...

  • C++入门07 --多继承,菱形继承,虚继承,虚基类

    多继承 C++允许一个类有多个父类,不建议使用,会增加程序设计的复杂度; Undergraduate类继承自Stu...

网友评论

    本文标题:第8篇:C++ 类多继承(后篇)

    本文链接:https://www.haomeiwen.com/subject/pgeibctx.html