• 不可或缺 Windows Native (22)


    [源码下载]


    不可或缺 Windows Native (22) - C++: 多重继承, 虚基类



    作者:webabcd


    介绍
    不可或缺 Windows Native 之 C++

    • 多重继承
    • 虚基类



    示例
    1、基类 1
    CppBase1.h

    #pragma once 
    
    #include <string>
    #include "CppBaseVirtual.h"
    
    using namespace std;
    
    namespace NativeDll
    {
        // virtual 代表 CppBaseVirtual 是 CppBase1 的虚基类(虚基类是在声明派生类时,指定继承方式时声明的)
        class CppBase1 : virtual public CppBaseVirtual
        {
    
        protected:
            string Name;
            float Salary;
    
        public:
            CppBase1(int number, string name, float salary);
    
        };
    }

    CppBase1.cpp

    /*
     * 基类 1
     */
    
    #include "pch.h" 
    #include "CppBase1.h" 
    
    using namespace NativeDll;
    
    CppBase1::CppBase1(int number, string name, float salary) :CppBaseVirtual(number), Name("cppbase1 " + name), Salary(salary)
    {
    
    }


    2、基类 2
    CppBase2.h

    #pragma once 
    
    #include <string>
    #include "CppBaseVirtual.h"
    
    using namespace std;
    
    namespace NativeDll
    {
        // virtual 代表 CppBaseVirtual 是 CppBase2 的虚基类(虚基类是在声明派生类时,指定继承方式时声明的)
        class CppBase2 : virtual CppBaseVirtual
        {
    
        protected:
            string Name;
            int Age;
    
        public:
            CppBase2(int number, string name, int age);
    
        };
    }

    CppBase2.cpp

    /*
     * 基类 2
     */
    
    #include "pch.h" 
    #include "CppBase2.h" 
    
    using namespace NativeDll;
    
    CppBase2::CppBase2(int number, string name, int age) :CppBaseVirtual(number), Name("cppbase2 " + name), Age(age)
    {
    
    }


    3、虚基类
    CppBaseVirtual.h

    #pragma once 
    
    #include <string>
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppBaseVirtual
        {
    
        private:
            int Number;
    
        public:
            CppBaseVirtual(int number);
    
        };
    }

    CppBaseVirtual.cpp

    /*
     * 用于演示虚基类
     *
     * 注:
     * 1、虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的
     * 2、一个基类可以在生成一个派生类时作为虚基类,也可以在生成一个派生类时不作为虚基类
     */
    
    #include "pch.h" 
    #include "CppBaseVirtual.h" 
    
    using namespace NativeDll;
    
    CppBaseVirtual::CppBaseVirtual(int number) :Number(number)
    {
    
    }


    4、派生类
    CppDerived.h

    #pragma once 
    
    #include <string>
    #include "CppBase1.h"
    #include "CppBase2.h"
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppDerived : public CppBase1, public CppBase2
        {
    
        public:
            CppDerived(int number, string name, float salary, int age);
    
            string Show();
    
        };
    }

    CppDerived.cpp

    /*
     * 派生类
     *
     *
     * 在多重继承的情况下:
     * 1、如果 A 是 B C D E 的基类,F 同时继承了 B C D E,那么实例化 F 时会保存 4 份 A 成员
     * 2、如果 A 是 B 的基类,A 是 C D E 的虚基类(虚基类会使得在继承间接共同基类时只保留一份成员),F 同时继承了 B C D E,那么实例化 F 时会保存 2 份 A 成员(从 C D E 的路径上保留一份,从 B 的路径上保留一份)
     *
     *
     * 本例中:
     * 1、CppBaseVirtual 是 CppBase1 和 CppBase2 的虚基类
     * 2、CppDerived 继承了 CppBase1 和 CppBase2(多重继承)
     * 3、此种情况,实例化 CppDerived 只会保留一份 CppBaseVirtual 成员(因为 CppBaseVirtual 是 CppBase1 和 CppBase2 的虚基类)
     * 4、C++ 编译器只会执行最后的派生类(CppDerived)对虚基类(CppBaseVirtual)的构造函数的调用,而忽略虚基类的直接派生类(CppBase1 和 CppBase2)对虚基类的构造函数的调用,这就保证了虚基类的数据成员不会被多次初始化
     */
    
    #include "pch.h" 
    #include "CppDerived.h" 
    #include "cppHelper.h"
    
    using namespace NativeDll;
    
    // 在无虚基类的情况下,派生类的构造函数中只需负责对其直接基类初始化
    // 如果有虚基类,且虚基类中定义了带参数的构造函数,且没有定义默认构造函数,那么派生类不仅要负责对其直接基类进行初始化,还要负责对虚基类初始化
    CppDerived::CppDerived(int number, string name, float salary, int age) :CppBaseVirtual(number), CppBase1(number, name, salary), CppBase2(number, name, age)
    {
    
    }
    
    string CppDerived::Show()
    {
        // 关于多重继承的二义性(ambiguous),如果派生类同时继承的多个基类有相同的成员,则调用这些成员时需显式指定其基类
        return CppBase1::Name + " " + float2string(Salary) + " " + int2string(Age);
    
        // 另外:当然,如果派生类与多个基类有相同成员的话,那么基类中的这些与派生类相同的成员都会被隐藏掉(即派生类中的成员会覆盖基类中的成员)
    }


    5、示例
    CppClass6.h

    #pragma once 
    
    #include <string>
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppClass6
        {
        public:
            string Demo();
        };
    }

    CppClass6.cpp

    /*
     * 多重继承(multiple inheritance), 虚基类(virtual base class)
     */
    
    #include "pch.h" 
    #include "CppClass6.h" 
    #include "CppDerived.h" 
    
    using namespace NativeDll;
    
    string CppClass6::Demo()
    {
        CppDerived derived(0, "webabcd", 100.0f, 35);
        string result = derived.Show(); // cppbase1 webabcd 100.00 35
    
        return result;
    }



    OK
    [源码下载]

  • 相关阅读:
    MySQL事务提交流程详解
    MySQL启动过程详解五:GTID的处理
    MySQL启动过程详解二:核心模块启动 init_server_components()
    网络安全:SQL注入,XSS攻击,CSRF攻击
    Dropdown下拉菜单
    VUE:身份证组件
    window系统下 解决MySQL 8报错sql_mode=only_full_group_by:this is incompatible with sql_mode=only_full_group_by
    上传图片:点击按钮后进入对话框,点击➕号直接上传图片,点击确定即保存
    VUE: TreeChart树形图
    vue生成二维码:vueqr二维码插件使用
  • 原文地址:https://www.cnblogs.com/webabcd/p/4642025.html
Copyright © 2020-2023  润新知