• C++中类的多继承


    在写这一主题的文章之前,在网上找到一篇很非常好的文章C++之继承与多态。就没有必要做重复造轮子的事件了,那就从这篇文章开始吧!

    在c++中一个类可以从多个基类中派生(即可以有多个父类),这就是多继承。多继承的方式主要有两种:

    1. 简单版本

    这里写图片描述 


    类C会同时拥有类A和类B的特性(属性和方法,也就是两个类的所有成员)。这种方式很简单这里就不多说,主要讲下面这种方式。


    2. 复杂版本


    这里写图片描述 

    同样的,这个结构中类C也会同时拥有类A和类B的特性,但这就会有一个问题,类B1和B2都继承自A,那么类C的对象会同时包含两个A的对象。这样就会带来很多歧义性。

    我们看一个典型的例子“沙发-床”: 

    这里写图片描述 
    类的关系图

    代码:

    #pragma once
    
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    class Furniture
    {
    public:
        Furniture(void) : m_weight(0){}
        Furniture(double weight) : m_weight(weight){}
        ~Furniture(void){}
    
        double GetWeight() const { return m_weight; }
        void SetWeight(double val) { m_weight = val; }
    
    private:
        double m_weight;
    
    };
    
    class Bed : public Furniture
    {
    public:
        Bed() : Furniture(), m_second(0) {}
        Bed(double weight, int second) : Furniture(weight), m_second(second){}
    
        void Sleep(int second) 
        {
            m_second = second;
            cout << "休息" << m_second << "秒..."<< endl;
        }
    
    
    private:
        int m_second;
    
    };
    
    class Sofa : public Furniture
    {
    public:
        Sofa() : Furniture() {}
        Sofa(double weight) : Furniture(weight){}
    
        void WatchTV(string  programme)
        {
            cout << "正在看" << programme << "节目..." << endl;
        }
    };
    
    class SleepSofa : public Bed, public Sofa
    {
    public:
        SleepSofa() : Bed(), Sofa() {}
        SleepSofa(double weight, int second) : Bed(weight, second), Sofa(weight) {}
    
        void FoldOut()
        {
            cout << "展开沙发当床用." << endl;
            Sleep(360);
        }
    };

    SleepSofa类继承自Bed和Sofa两个类,因此,SleepSofa类拥有这两个类的特性,但在实际编码中会存在如下几个问题。

    1.SleepSofa类该如何定义?

    Class SleepSofa : public Bed, public Sofa
    {
        …
    }
    

    构造顺序为:Bed sofa sleepsofa (也就是书写的顺序)

    2.Bed和Sofa类都继承自Furniture,都有Weight属性也都有GetWeight和SetWeight方法,在SleepSofa类中使用这些属性和方法时,如何确定调用的是哪个类的成员?

    我们看一下测试样例:

    void Test()
    {
        SleepSofa sleepSofa;
        sleepSofa.SetWeight(55);
        double weight = sleepSofa.GetWeight();
    }

    这时会有以下错误:

    .cpp(76): error C3861: ‘SetWeight’: identifier not found 
    error C2385: ambiguous access of ‘GetWeight’

    就是说SetWeight和GetWeight是有歧义的。

    解决方法: 
    (1). 可以使用完全限定名(即加上类的作用域)的方式,比如:

    SleepSofa sleepSofa;
    sleepSofa.Bed::SetWeight(55);
    sleepSofa.Sofa::SetWeight(80);
    

    这时可以看到sleepSofa对象有两个Furniture对象。如下: 

    这里写图片描述

    (2). 虚继承 
    倘若,我们定义一个SleepSofa对象,让我们分析一下它的构造过程:它会构造Bed类和Sofa类,但Bed类和Sofa类都有一个父类,因此Furniture类被构造了两次,这是不合理的,因此,我们引入了虚继承的概念。

    class Furniture{……};
    
    class Bed : virtual public Furniture{……}; // 这里我们使用虚继承
    
    class Sofa : virtual public Furniture{……};// 这里我们使用虚继承
    
    class SleepSofa : public Bed, public Sofa {……};
    

    这样,Furniture类就只会构造一次,sleepSofa对象只会包含一个Furniture对象。 
    我们看一下测试样例:

    SleepSofa sleepSofa;
    sleepSofa.SetWeight(80);
    

    这时我们Debug模式可以看到SleepSofa的m_weight值都是80。 

    这里写图片描述

    这里虽然显示着两个Furniture对象,但其实指向的是同一个对象。我们可以看看它们的地址都是一样的。 

    这里写图片描述


    总结

    1. 在程序设计中最好不要出现多继承,要有也是继承多个作为接口使用抽象类(只声明需要的功能,没有具体的实现)。因为出现一般的多继承本身就是一种不好的面向对象程序设计。
    2. 在出现版本2的多继承时使用虚继承的方式。 
  • 相关阅读:
    python异常
    linux下进行base64编码解码
    mybatis参数映射
    Mybatis--映射器注解
    Mybatis--映射器注解
    Mybatis--Statement Builders
    Mybatis--Statement Builders
    在MySql中如何定义像Java中类型的Boolean类型
    在MySql中如何定义像Java中类型的Boolean类型
    Navicat导入导出数据表
  • 原文地址:https://www.cnblogs.com/aabbcc/p/5969969.html
Copyright © 2020-2023  润新知