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

[源码下载]


不可或缺 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
[源码下载]

posted @ 2015-07-16 08:09  webabcd  阅读(1606)  评论(0编辑  收藏  举报