• 不可或缺 Windows Native (21)


    [源码下载]


    不可或缺 Windows Native (21) - C++: 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)



    作者:webabcd


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

    • 继承
    • 组合
    • 派生类的构造函数和析构函数
    • 基类与派生类的转换
    • 子对象的实例化
    • 基类成员的隐藏(派生类成员覆盖基类成员)



    示例
    1、基类
    CppAnimal.h

    #pragma once 
    
    #include <string>
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppAnimal
        {
        private:
            int Number;
    
        protected: 
            string Name;
            int Age;
    
        public:
            string Show();
    
            CppAnimal(int number);
        };
    }

    CppAnimal.cpp

    /*
     * 用于基类的演示
     */
    
    #include "pch.h" 
    #include "CppAnimal.h" 
    #include "cppHelper.h"
    
    using namespace NativeDll;
    
    string CppAnimal::Show()
    {
        return "animal: " + int2string(Number) + " " + Name;
    }
    
    CppAnimal::CppAnimal(int number) :Number(number)
    {
        Name = "动物";
    }


    2、派生类
    CppTiger.h

    #pragma once 
    
    #include <string>
    #include "CppAnimal.h"
    #include "CppEmployee.h"
    
    using namespace std;
    
    namespace NativeDll
    {
        /*
         * 基类(base class)
         * 派生类(derived class)
         * 继承(inheritance)
         * 组合(composition) - 在一个类中以另一个类的对象作为数据成员的,称为类的组合
         *
         *
         * public 继承:派生类不能访问基类的私有成员;基类的公有成员在派生类中依然是公有成员;基类的保护成员在派生类中依然是保护成员
         * private 继承(默认值):派生类不能访问基类的私有成员;基类的公有成员在派生类中变为私有成员;基类的保护成员在派生类中变为私有成员
         * protected 继承:派生类不能访问基类的私有成员;基类的公有成员在派生类中变为保护成员;基类的保护成员在派生类中依然是保护成员
         */
    
        class CppTiger : public CppAnimal // 我是 public 继承,这是最常用的
        // class CppTiger : private CppAnimal // 我是 private 继承
        // class CppTiger : protected CppAnimal // 我是 protected 继承
        // class CppTiger : CppAnimal // 默认是 private 继承
        {
    
        private:
            string NickName;
    
            // 在一个类中以另一个类的对象作为数据成员的,称为类的组合
            CppEmployee employee; // 我是 CppTiger 的子对象(subobject)
    
        protected:
            // 派生类中的属性,如果其属性名与基类中的一样(不考虑属性的类型),则隐藏基类中的相应的属性(即派生类中的属性覆盖了基类中的属性)
            float Age;
    
        public:
            // 构造函数不会从基类继承过来,需要在派生类中自己写(注:析构函数也不会从基类继承过来,需要在派生类中自己写)
            CppTiger(int number);
            CppTiger(int number, string name, string nickName);
    
            // 用于演示如何在构造函数中,用简单的方式实例化子对象
            CppTiger(int tigerNumber, string tigerName, int employeeNumber, string employeeName);
    
            // 派生类中的函数,如果其函数名和参数与基类中的一样(不考虑返回值类型),则隐藏基类中的相应的函数(即派生类中的函数覆盖了基类中的函数)
            string Show();
        };
    }

    CppTiger.cpp

    /*
     * 用于派生类的演示
     */
    
    #include "pch.h" 
    #include "CppTiger.h" 
    #include "cppHelper.h"
    
    using namespace NativeDll;
    
    // 在派生类的构造函数中调用基类的构造函数(注:在无虚基类的情况下,派生类的构造函数中只需负责对其直接基类初始化)
    CppTiger::CppTiger(int number) :CppAnimal(number)
    {
    
    }
    
    // 在派生类的构造函数中调用基类的构造函数,初始化派生类的私有成员
    CppTiger::CppTiger(int number, string name, string nickName) :CppAnimal(number), NickName(nickName)
    {
        // 初始化基类的保护成员
        Name = name;
    }
    
    // 在构造函数中,用简单的方式实例化子对象(本例实例化了 employee 对象)
    CppTiger::CppTiger(int tigerNumber, string tigerName, int employeeNumber, string employeeName) :CppAnimal(tigerNumber), employee(employeeNumber, employeeName)
    {
        // 如果用此种方式实例化子对象,则其实子对象会被实例化 2 次(声明时的 CppEmployee employee; 会被实例化一次,此处又会被实例化一次)
        // this->employee = CppEmployee(employeeNumber, employeeName);
    
        Name = tigerName;
    }
    
    // 我是 CppTiger 的 Show() 函数,由于与 CppAnimal 中的 Show() 函数同名且参数相同,所以 CppAnimal 中的 Show() 函数会被隐藏掉。也可以说 CppTiger 的 Show() 函数覆盖了 CppAnimal 中的 Show() 函数
    string CppTiger::Show()
    {
        // 在派生类中调用基类成员的话,需要通过“::”来实现
        // 本例中如果要调用基类的 Show() 的话,就这么写 CppAnimal::Show()
        // 如果直接调用 Show() 的话就死循环了
    
        return "tiger: " + Name + ", employee: " + employee.Show() + ", " + CppAnimal::Show();
    }


    3、示例
    CppClass5.h

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

    CppClass5.cpp

    /*
     * 继承, 组合, 派生类的构造函数和析构函数, 基类与派生类的转换, 子对象的实例化, 基类成员的隐藏(派生类成员覆盖基类成员)
     */
    
    #include "pch.h" 
    #include "CppClass5.h" 
    #include "CppTiger.h"
    
    using namespace NativeDll;
    
    string cppclass5_demo1();
    string cppclass5_demo2();
    void cppclass5_demo3();
    
    string CppClass5::Demo()
    {
        string r1 = cppclass5_demo1();
        string r2 = cppclass5_demo2();
        string result = r1 + "
    " + r2;
    
        // 基类与派生类的转换
        cppclass5_demo3();
    
        return result;
    }
    
    
    string cppclass5_demo1()
    {
        // 此处演示了派生类的构造函数
        CppTiger tiger(100, "老虎", "大猫");
    
        // 此处演示了基类成员的隐藏(派生类成员覆盖基类成员)
        string result = tiger.Show(); // tiger: 老虎, employee: 888 webabcd, animal: 100 老虎
    
        return result;
    }
    
    
    string cppclass5_demo2()
    {
        // 此处演示了派生类的构造函数,以及同时实例化子对象
        CppTiger tiger2(100, "老虎", 200, "wanglei");
    
        // 此处演示了基类成员的隐藏(派生类成员覆盖基类成员)
        string result = tiger2.Show(); // tiger: 老虎, employee: 200 wanglei, animal: 100 老虎
    
        return result;
    }
    
    
    // 基类与派生类的转换
    void cppclass5_demo3()
    {
        // 派生类对象可以赋值给基类对象(反之不可),基类对象无法使用派生类对象的特性
        CppTiger tiger(100, "老虎", 200, "wanglei");
        CppAnimal animal = tiger;
        // 调用的是基类的 Show() 函数(但是数据成员是通过 CppTiger 实例化而来的)
        string result = animal.Show(); // animal: 100 老虎
    
    
        // 指向基类对象的指针,也可以指向派生类对象(反之不可),但是无法使用派生类对象的特性
        CppAnimal animal2(100);
        CppAnimal *animal2Pointer = &animal2;
        CppTiger tiger2(200, "老虎", 300, "wanglei");
        animal2Pointer = &tiger2;
        // 调用的是基类的 Show() 函数(但是数据成员是通过 CppTiger 实例化而来的)
        string result2 = animal2Pointer->Show(); // animal: 200 老虎
    }



    OK
    [源码下载]

  • 相关阅读:
    Java_基础_内存管理
    Reflux中文教程——action
    Reflux中文教程——概览
    包含块、层叠上下文、BFC
    DOM编程的性能问题
    JavaScript数据存取的性能问题
    闭包
    JavaScript中的继承
    JavaScript中的静态成员
    JavaScript中的私有属性
  • 原文地址:https://www.cnblogs.com/webabcd/p/4631930.html
Copyright © 2020-2023  润新知