程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 不可或缺 Windows Native (23),native23

不可或缺 Windows Native (23),native23

編輯:C++入門知識

不可或缺 Windows Native (23),native23


[源碼下載]


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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved