zoukankan      html  css  js  c++  java
  • 不可或缺 Windows Native (23)

    [源码下载]


    不可或缺 Windows Native (23) - C++: 虚函数



    作者:webabcd


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

    • 虚函数



    示例
    1、基类
    CppHuman.h

    #pragma once 
    
    #include <string>
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppHuman
        {
    
        protected:
            string Name;
    
        public:
            // 我是虚函数
            virtual string Show(); 
            
            // 我是纯虚函数(后面的“=0”只起形式上的作用,用于告诉编译器:“这是纯虚函数”)
            // 纯虚函数只有声明,没有定义,其具体的功能是留给派生类定义的
            // 凡是包含纯虚函数的类都是抽象类,抽象类是无法实例化的,因为纯虚函数是不能被调用的
            // virtual string Display() = 0; 
    
            CppHuman(string name);
    
            // 我是 virtual 的析构函数
            virtual ~CppHuman();
    
        };
    }

    CppHuman.cpp

    /*
     * 基类
     */
    
    #include "pch.h" 
    #include "CppHuman.h" 
    #include "cppHelper.h"
    
    using namespace NativeDll;
    
    string CppHuman::Show()
    {
        return "human: " + Name;
    }
    
    CppHuman::CppHuman(string name) : Name(name)
    {
    
    }
    
    CppHuman::~CppHuman()
    {
    
    }


    2、派生类
    CppChild.h

    #pragma once 
    
    #include <string>
    #include "CppHuman.h"
    
    using namespace std;
    
    namespace NativeDll
    {
        class CppChild : public CppHuman
        {
    
        public: 
            // 由于基类 CppHuman 的 Show() 函数是虚函数,所以其所有直接或间接派生类中,如果声明了此函数则均为虚函数(virtual 可以省略)
            virtual string Show();
    
            CppChild(string name);
    
            ~CppChild();
    
        };
    }

    CppChild.cpp

    /*
     * 派生类(基类是 CppHuman)
     */
    
    #include "pch.h" 
    #include "CppChild.h" 
    #include "cppHelper.h"
    
    using namespace NativeDll;
    
    string CppChild::Show()
    {
        return "child: " + Name;
    }
    
    CppChild::CppChild(string name) : CppHuman(name)
    {
    
    }
    
    CppChild::~CppChild()
    {
    
    }


    3、示例
    CppClass7.h

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

    CppClass7.cpp

    /*
     * 虚函数
     */
    
    #include "pch.h" 
    #include "CppClass7.h" 
    #include "CppChild.h"
    
    using namespace NativeDll;
    
    void cppclass7_demo1();
    void cppclass7_demo2();
    
    string CppClass7::Demo()
    {
        // 虚函数
        cppclass7_demo1();
    
        // virtual 的析构函数
        cppclass7_demo2();
    
    
        return "看代码及注释吧";
    }
    
    
    
    // 虚函数
    void cppclass7_demo1()
    {
        // 不使用虚函数的示例:参见 CppClass5.cpp 中的“基类与派生类的转换”
    
        // 以下演示了如何使用虚基类
        CppHuman human("webabcd");
        CppChild child("diandian");
    
        // 指针指向基类,调用虚函数后执行的是基类的虚函数
        CppHuman *humanPointer = &human;
        string result = humanPointer->Show(); // human: webabcd
    
        // 指向基类的指针改为指向派生类,调用虚函数后执行的是派生类的虚函数
        humanPointer = &child;
        result = humanPointer->Show(); // child: diandian
    
    
        // 像上面这种方式是在程序运行阶段把虚函数和类对象“绑定”在一起的,因此此过程称为动态关联(dynamic binding)或滞后关联(late binding),其属于动态多态性
        // 如果使用了虚函数,则编译器会为该类构造一个虚函数表(virtual function table,简称 vtable),它是一个指针数组,存放每个虚函数的入口地址,据此可做静态关联和动态关联
    }
    
    
    
    // virtual 的析构函数
    void cppclass7_demo2()
    {
        // 一般来说,清理派生类时,会先调用派生类的析构函数,然后调用基类的析构函数
        // 但是下面这种情况例外
        CppHuman *pt = new CppChild("diandian");
        delete pt;
        // 此时,如果基类的析构函数不是 virtual 的,则只会执行基类的析构函数
        // 此时,如果基类的析构函数是 virtual 的,则会先执行派生类的析构函数,再执行基类的析构函数
        // 所以,最好把基类的析构函数声明为虚函数(其会使所有派生类的析构函数都自动变为虚函数),以避免清理不彻底
    }



    OK
    [源码下载]

  • 相关阅读:
    前端cookie操作用到的一些小总结
    sublime 官方正版,自己用的插件配置,最轻量级安装流程
    Node.js 终端输出颜色设置
    Mac中设置别名 (转载)
    Swift 3 使用objc_setAssociatedObject
    ruby 笔记
    编程模式
    rvm pod gem 等常用命令
    node.js 笔记
    Node.js 对象合并
  • 原文地址:https://www.cnblogs.com/webabcd/p/4650172.html
Copyright © 2011-2022 走看看