欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章徹底弄懂C++虛函數(shù)的實(shí)現(xiàn)機(jī)制

 更新時(shí)間:2021年06月30日 12:57:12   作者:彼 方  
C++中的虛函數(shù)的作用主要是實(shí)現(xiàn)了多態(tài)的機(jī)制,基類定義虛函數(shù),子類可以重寫該函數(shù),在派生類中對(duì)基類定義的虛函數(shù)進(jìn)行重寫時(shí),需要在派生類中聲明該方法為虛方法,這篇文章主要給大家介紹了關(guān)于如何通過(guò)一篇文章徹底弄懂C++虛函數(shù)的實(shí)現(xiàn)機(jī)制,需要的朋友可以參考下

1、虛函數(shù)簡(jiǎn)介

C++中有兩種方式實(shí)現(xiàn)多態(tài),即重載和覆蓋。

  • 重載:是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(參數(shù)個(gè)數(shù)不同、參數(shù)類型不同或者兩者都不同)。
  • 覆蓋:是指子類重新定義父類虛函數(shù)的做法,簡(jiǎn)而言之就是用父類型別的指針指向其子類的實(shí)例,然后通過(guò)父類的指針調(diào)用實(shí)際子類的成員函數(shù)。這種技術(shù)可以讓父類的指針擁有“多種形態(tài)”,這是一種泛型技術(shù)。所謂泛型技術(shù),說(shuō)白了就是試圖使用不變的代碼來(lái)實(shí)現(xiàn)可變的算法,比如:模板元編程是在編譯期完成的泛型技術(shù),RTTI、虛函數(shù)則是在運(yùn)行時(shí)完成的泛型技術(shù)。

關(guān)于虛函數(shù)的具體使用方法,建議大家先去閱讀相關(guān)的C++的書籍,本文只剖析虛函數(shù)的實(shí)現(xiàn)機(jī)制,讓大家對(duì)虛函數(shù)有一個(gè)更加清晰的認(rèn)識(shí),并不對(duì)虛函數(shù)的具體使用方法作過(guò)多介紹。本文是依據(jù)個(gè)人經(jīng)驗(yàn)和查閱相關(guān)資料最終編寫的,如有錯(cuò)漏,希望大家多多指正。

2、虛函數(shù)表簡(jiǎn)介

學(xué)過(guò)C++的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過(guò)虛函數(shù)表(Virtual Table,簡(jiǎn)稱為V-Table)來(lái)實(shí)現(xiàn)的。虛函數(shù)表主要存儲(chǔ)的是指向一個(gè)類的虛函數(shù)地址的指針,通過(guò)使用虛函數(shù)表,繼承、覆蓋的問(wèn)題都都得到了解決。假如一個(gè)類有虛函數(shù),當(dāng)我們構(gòu)建這個(gè)類的實(shí)例時(shí),將會(huì)額外分配一個(gè)指向該類虛函數(shù)表的指針,當(dāng)我們用父類的指針來(lái)操作一個(gè)子類的時(shí)候,這個(gè)指向虛函數(shù)表的指針就派上用場(chǎng)了,它指明了此時(shí)應(yīng)該使用哪個(gè)虛函數(shù)表,而虛函數(shù)表本身就像一個(gè)地圖一樣,為編譯器指明了實(shí)際所應(yīng)該調(diào)用的函數(shù)。指向虛函數(shù)表的指針是存在于對(duì)象實(shí)例中最前面的位置(這是為了保證取到虛函數(shù)表的有最高的性能——如果有多層繼承或是多重繼承的情況下),這就意味著理論上我們可以通過(guò)對(duì)象實(shí)例的地址得到這張?zhí)摵瘮?shù)表(實(shí)際上確實(shí)可以做到),然后對(duì)虛函數(shù)表進(jìn)行遍歷,并調(diào)用其中的函數(shù)。

前面說(shuō)了一大堆理論,中看不中用,下面還是通過(guò)一個(gè)實(shí)際的例子驗(yàn)證一下前面講的內(nèi)容,首先定義一個(gè)Base類,該類有三個(gè)虛函數(shù),代碼如下:

#include <iostream>
#include <string>

typedef void (*Fun)(void);

class Base
{
public:
    virtual void f()
    {
        std::cout << "Base::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base::h()" << std::endl;
    }
};

接下來(lái)按照前面的說(shuō)法,我們通過(guò)Base類的實(shí)例對(duì)象base來(lái)獲取虛函數(shù)表,代碼如下:

int main(int argc, char* argv[])
{
    Base base;
    Fun fun = nullptr;

    std::cout << "指向虛函數(shù)表指針的地址:" << (long*)(&base) << std::endl;
    std::cout << "虛函數(shù)表的地址:" << (long*)*(long*)(&base) << std::endl;

    fun = (Fun)*((long*)*(long*)(&base));
    std::cout << "虛函數(shù)表中第一個(gè)函數(shù)的地址:" << (long*)fun << std::endl;
    fun();

    fun = (Fun)*((long*)*(long*)(&base) + 1);
    std::cout << "虛函數(shù)表中第二個(gè)函數(shù)的地址:" << (long*)fun << std::endl;
    fun();

    fun = (Fun)*((long*)*(long*)(&base) + 2);
    std::cout << "虛函數(shù)表中第三個(gè)函數(shù)的地址:" << (long*)fun << std::endl;
    fun();
}

運(yùn)行結(jié)果圖2-1所示(Linux 3.10.0 + GCC 4.8.5):

圖2-1 程序運(yùn)行結(jié)果

在上面的例子中我們通過(guò)把&base強(qiáng)制轉(zhuǎn)換成long *,來(lái)取得指向虛函數(shù)表的指針的地址,然后對(duì)這個(gè)地址取值就可以得到對(duì)應(yīng)的虛函數(shù)表了。得到對(duì)應(yīng)虛函數(shù)表的首地址后,就可以通過(guò)不斷偏移該地址,依次得到指向真實(shí)虛函數(shù)的指針了。這么說(shuō)有點(diǎn)繞也有點(diǎn)暈,下面通過(guò)一幅圖解釋一下前面說(shuō)的內(nèi)容,詳見(jiàn)圖2-2

圖2-2 基類虛函數(shù)表內(nèi)存布局

當(dāng)然,上述內(nèi)容也可以在GDB中調(diào)試驗(yàn)證,后續(xù)的內(nèi)容也將全部在GDB下直接驗(yàn)證,調(diào)試的示例見(jiàn)圖2-3:

圖2-3 GDB查看基類虛函數(shù)表內(nèi)存布局

3、有繼承關(guān)系的虛函數(shù)表剖析

前面分析虛函數(shù)表的場(chǎng)景是沒(méi)有繼承關(guān)系的,然而在實(shí)際開(kāi)發(fā)中,沒(méi)有繼承關(guān)系的虛函數(shù)純屬浪費(fèi)表情,所以接下來(lái)我們就來(lái)看看有繼承關(guān)系下虛函數(shù)表會(huì)呈現(xiàn)出什么不一樣的特點(diǎn),分析的時(shí)候會(huì)分別就單繼承無(wú)虛函數(shù)覆蓋、單繼承有虛函數(shù)覆蓋、多重繼承、多層繼承這幾個(gè)場(chǎng)景進(jìn)行說(shuō)明。

3.1、單繼承無(wú)虛函數(shù)覆蓋的情況

先定義一個(gè)Base類,再定義一個(gè)Derived類,Derived類繼承于Base類,代碼如下:

#include <iostream>
#include <string>

class Base
{
public:
    virtual void f()
    {
        std::cout << "Base::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base::h()" << std::endl;
    }
};

class Derived : public Base
{
public:
    virtual void f1()
    {
        std::cout << "Derived::f1()" << std::endl;
    }

    virtual void g1()
    {
        std::cout << "Derived::g1()" << std::endl;
    }

    virtual void h1()
    {
        std::cout << "Derived::h1()" << std::endl;
    }
};

繼承關(guān)系如圖3-1所示:

圖3-1 類繼承關(guān)系UML圖

測(cè)試的代碼如下,因?yàn)榈认乱褂肎DB來(lái)驗(yàn)證,所以就隨便寫點(diǎn),定義個(gè)Derived類實(shí)例就行了

int main(int argc, char* argv[])
{
    Derived derived;
    derived.f();
}

派生類Derived的虛函數(shù)表內(nèi)存布局如圖3-2所示:

圖3-2 單繼承無(wú)虛函數(shù)覆蓋情況下派生類虛函數(shù)表內(nèi)存布局

接下來(lái)就用GDB調(diào)試一下,驗(yàn)證上圖的內(nèi)存布局是否正確,如圖3-3所示:

圖3-3 GDB查看單繼承無(wú)虛函數(shù)覆蓋情況下派生類虛函數(shù)表內(nèi)存布局

從調(diào)試結(jié)果可以看出圖3-2是正確的,Derived的虛函數(shù)表中先放Base的虛函數(shù),再放Derived的虛函數(shù)。

3.2、單繼承有虛函數(shù)覆蓋的情況

派生類覆蓋基類的虛函數(shù)是很有必要的事情,不這么做的話虛函數(shù)的存在將毫無(wú)意義。下面我們就來(lái)看一下如果派生類中有虛函數(shù)覆蓋了基類的虛函數(shù)的話,對(duì)應(yīng)的虛函數(shù)表會(huì)是一個(gè)什么樣子。還是老規(guī)矩先定義兩個(gè)有繼承關(guān)系的類,注意一下我這里只覆蓋了基類的g()

#include <iostream>
#include <string>

class Base
{
public:
    virtual void f()
    {
        std::cout << "Base::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base::h()" << std::endl;
    }
};

class Derived : public Base
{
public:
    virtual void f1()
    {
        std::cout << "Derived::f1()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Derived::g()" << std::endl;
    }

    virtual void h1()
    {
        std::cout << "Derived::h1()" << std::endl;
    }
};

繼承關(guān)系如圖3-4所示:

圖3-4 類繼承關(guān)系UML圖

測(cè)試的代碼如下,因?yàn)榈认乱褂肎DB來(lái)驗(yàn)證,所以就隨便寫點(diǎn),定義個(gè)Derived類實(shí)例就行了

int main(int argc, char* argv[])
{
    Derived derived;
    derived.g();
}

派生類Derived的虛函數(shù)表內(nèi)存布局如圖3-5所示:

圖3-5 單繼承有虛函數(shù)覆蓋情況下派生類虛函數(shù)表內(nèi)存布局

接下來(lái)就用GDB調(diào)試一下,驗(yàn)證上圖的內(nèi)存布局是否正確,如圖3-6所示:

圖3-6 GDB查看單繼承有虛函數(shù)覆蓋情況下派生類虛函數(shù)表內(nèi)存布局

從調(diào)試結(jié)果可以看出圖3-5是正確的,并且可以得到以下幾點(diǎn)信息:

覆蓋的g()被放到了虛表中原來(lái)父類虛函數(shù)的位置沒(méi)有被覆蓋的虛函數(shù)位置排序依舊不變

有了前面的理論基礎(chǔ),我們可以知道對(duì)于下面的代碼,由base所指的內(nèi)存中的虛函數(shù)表的Base::g()的位置已經(jīng)被Derived::g()所取代,于是在實(shí)際調(diào)用發(fā)生時(shí),調(diào)用的是Derived::g(),從而實(shí)現(xiàn)了多態(tài)

int main(int argc, char* argv[])
{
    Base* base = new Derived();
    base->f();
    base->g();
    base->h();
}

輸出結(jié)果如圖3-7所示:

圖3-7 程序運(yùn)行結(jié)果

注意:在前面的例子中,我們分配內(nèi)存的實(shí)例對(duì)象的類型是Derived,但是卻用Base的指針去引用它,這個(gè)過(guò)程中數(shù)據(jù)并沒(méi)有發(fā)生任何的轉(zhuǎn)換,實(shí)例的真實(shí)類型依舊是Derived,但是由于我們使用時(shí)用的是Base類型,所以函數(shù)調(diào)用要依據(jù)Base類來(lái),不能胡亂調(diào)用,比如說(shuō)我們此時(shí)是無(wú)法調(diào)用Derived的f1()和h1()的。由于這個(gè)是個(gè)單繼承,不存在虛函數(shù)表選擇問(wèn)題,相對(duì)比較簡(jiǎn)單。

3.3、多重繼承的情況

多重繼承就不分開(kāi)講有覆蓋和無(wú)覆蓋的情況了,其實(shí)結(jié)合前面講的就差不多知道是什么個(gè)情況了,下面的例子中會(huì)設(shè)計(jì)成派生類既有自己的虛函數(shù),又有用于覆蓋基類的虛函數(shù),這樣就能兼顧有覆蓋和無(wú)覆蓋的情況了。

類的設(shè)計(jì)如下:

#include <iostream>
#include <string>

class Base1
{
public:
    virtual void f()
    {
        std::cout << "Base1::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base1::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base1::h()" << std::endl;
    }
};

class Base2
{
public:
    virtual void f()
    {
        std::cout << "Base2::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base2::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base2::h()" << std::endl;
    }
};

class Base3
{
public:
    virtual void f()
    {
        std::cout << "Base3::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base3::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base3::h()" << std::endl;
    }
};

class Derived : public Base1, public Base2, public Base3
{
public:
    virtual void f()
    {
        std::cout << "Derived::f()" << std::endl;
    }

    virtual void g1()
    {
        std::cout << "Derived::g1()" << std::endl;
    }

    virtual void h1()
    {
        std::cout << "Derived::h1()" << std::endl;
    }
};

繼承關(guān)系如圖3-8所示:

圖3-8 類繼承關(guān)系UML圖

測(cè)試的代碼如下:

int main(int argc, char* argv[])
{
    Derived* d = new Derived();
    Base1* b1 = d;
    Base2* b2 = d;
    Base3* b3 = d;
    std::cout << (long*)(*(long*)b1) << std::endl;
    std::cout << (long*)(*(long*)b2) << std::endl;
    std::cout << (long*)(*(long*)b3) << std::endl;
}

輸出結(jié)果如圖3-9所示:

圖3-9 程序運(yùn)行結(jié)果

輸出信息非常有趣,明明b1、b2、b3指向的都是d,但是它們各自取出來(lái)的虛函數(shù)表的地址卻完全不同,按理來(lái)說(shuō)不是應(yīng)該相同嗎?別急,下面我們通過(guò)圖3-10來(lái)看一看多繼承下派生類虛函數(shù)表的內(nèi)存布局是什么樣的

圖3-10 多重繼承情況下派生類虛函數(shù)表內(nèi)存布局

從圖3-10中可以看出以下幾點(diǎn)信息:

  • 在派生類中,每個(gè)基類都有一個(gè)屬于自己的虛函數(shù)表
  • 派生類自己特有的虛函數(shù)被放到了第一個(gè)基類的表中(第一個(gè)基類是按照繼承順序來(lái)確定的)

這里我們就會(huì)得出一個(gè)新問(wèn)題了,對(duì)于上面例子中的b1,這個(gè)沒(méi)啥問(wèn)題,因?yàn)樗念愋虰ase1就是第一個(gè)被繼承的,所以我們當(dāng)然可以認(rèn)為這個(gè)不會(huì)出任何問(wèn)題,但是對(duì)于b2呢,它被繼承的位置可不是第一個(gè)啊,運(yùn)行時(shí)要怎么確定它的虛函數(shù)表呢?它有沒(méi)有可能一不小心找到Base1的虛函數(shù)去?恰好這個(gè)例子中幾個(gè)基類的虛函數(shù)名字和參數(shù)又都是完全相同的。這里其實(shí)就涉及到編譯器的處理了,當(dāng)我們執(zhí)行賦值操作Base2* b2 = d;時(shí),編譯器會(huì)自動(dòng)把b2的虛函數(shù)表指針指向正確的位置,這個(gè)過(guò)程應(yīng)該是編譯器做的,所以虛函數(shù)所實(shí)現(xiàn)的多態(tài)應(yīng)該是“靜動(dòng)結(jié)合”的,有部分工作需要在編譯時(shí)期完成的。

下面我們依然借助GDB來(lái)看一下實(shí)際的內(nèi)存布局,詳見(jiàn)圖3-11,從調(diào)試信息中可以看出此時(shí)確實(shí)有三張?zhí)摵瘮?shù)表,對(duì)應(yīng)三個(gè)基類

圖3-11 GDB查看多重繼承情況下派生類虛函數(shù)表內(nèi)存布局

第一張表的數(shù)據(jù)如圖3-12所示,可以看到和圖3-10描述的內(nèi)容是一致的,Derived自己特有的虛函數(shù)確實(shí)被加入到了第一張表中了,這里指示虛函數(shù)表結(jié)束的表示好像是那個(gè)0xfffffffffffffff8,不知道是不是固定的,有知道的小伙伴麻煩評(píng)論區(qū)告訴我一下謝謝

圖3-12 派生類第一張?zhí)摵瘮?shù)表

第二張表的數(shù)據(jù)如圖3-13所示,這里的結(jié)束符變成了0xfffffffffffffff0,搞不懂

圖3-13 派生類第二張?zhí)摵瘮?shù)表

第三張表的數(shù)據(jù)如圖3-14所示,這里的結(jié)束符終于是0x0了

圖3-14 派生類第三張?zhí)摵瘮?shù)表

補(bǔ)充說(shuō)明:如果繼承的某個(gè)類沒(méi)有虛函數(shù)的話,比如說(shuō)將上面的Base2修改為以下格式:

class Base2
{
public:
    void f()
    {
        std::cout << "Base2::f()" << std::endl;
    }

    void g()
    {
        std::cout << "Base2::g()" << std::endl;
    }

    void h()
    {
        std::cout << "Base2::h()" << std::endl;
    }
};

main函數(shù)不變,再運(yùn)行以下程序,輸出結(jié)果如圖3-15所示,說(shuō)明此時(shí)就沒(méi)有指向Base2虛函數(shù)表的指針了,因?yàn)樗緛?lái)就沒(méi)有虛函數(shù)表

圖3-15 程序運(yùn)行結(jié)果

3.4、多層繼承的情況

多層繼承的在有前面的基礎(chǔ)上來(lái)理解就非常簡(jiǎn)單了,測(cè)試程序如下:

#include <iostream>
#include <string>

class Base
{
public:
    virtual void f()
    {
        std::cout << "Base::f()" << std::endl;
    }

    virtual void g()
    {
        std::cout << "Base::g()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "Base::h()" << std::endl;
    }
};

class Derived : public Base
{
public:
    virtual void f()
    {
        std::cout << "Derived::f()" << std::endl;
    }

    virtual void g1()
    {
        std::cout << "Derived::g1()" << std::endl;
    }
};

class DDerived : public Derived
{
public:
    virtual void f()
    {
        std::cout << "DDerived::f()" << std::endl;
    }

    virtual void h()
    {
        std::cout << "DDerived::h()" << std::endl;
    }

    virtual void g2()
    {
        std::cout << "DDerived::g2()" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    DDerived dd;
    dd.f();
}

繼承關(guān)系如圖3-16所示:

圖3-16 類繼承關(guān)系UML圖

派生類DDerived的虛函數(shù)表內(nèi)存布局如圖3-17所示:

圖3-17 多層繼承情況下派生類虛函數(shù)表內(nèi)存布局

多層繼承的情況這里就不使用GDB去看內(nèi)存布局了,比較簡(jiǎn)單,大家可以自行去測(cè)試一下。

4、總結(jié)

本文先對(duì)虛函數(shù)的概念進(jìn)行了簡(jiǎn)單介紹,引出了虛函數(shù)表這個(gè)實(shí)現(xiàn)虛函數(shù)的關(guān)鍵要素,然后對(duì)不同繼承案例下虛函數(shù)表的內(nèi)存布局進(jìn)行說(shuō)明,并使用GDB進(jìn)行實(shí)戰(zhàn)驗(yàn)證。相信看完這篇文章后聰明的你會(huì)對(duì)虛函數(shù)有更加深刻的理解了。

到此這篇關(guān)于C++虛函數(shù)實(shí)現(xiàn)機(jī)制的文章就介紹到這了,更多相關(guān)C++虛函數(shù)實(shí)現(xiàn)機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言詳細(xì)講解常用字符串處理函數(shù)

    C語(yǔ)言詳細(xì)講解常用字符串處理函數(shù)

    在日常編程中,對(duì)于字符串的操作中我們都很習(xí)慣的使用一些C庫(kù)中自帶的函數(shù),并且關(guān)于字符串的操作函數(shù)基本都在 string.h 這個(gè)頭文件中。關(guān)于C庫(kù)字符串常用處理函數(shù)也是平時(shí)面試或者考試過(guò)程中非常喜歡考的,本文將帶大家手動(dòng)來(lái)實(shí)現(xiàn)這些常用函數(shù)
    2022-05-05
  • Qt數(shù)據(jù)庫(kù)應(yīng)用之超級(jí)自定義委托

    Qt數(shù)據(jù)庫(kù)應(yīng)用之超級(jí)自定義委托

    Qt中需要用到自定義委托的情形很多,比如提供下拉框選擇,進(jìn)度條展示下載進(jìn)度啥的,默認(rèn)的單元格是沒(méi)有這些效果的,需要自己?jiǎn)为?dú)用委托的形式來(lái)展示。本文將為大家介紹Qt中如何進(jìn)行超級(jí)自定義委托,需要的可以參考一下
    2022-03-03
  • C++ 獲取dll當(dāng)前路徑下所有文件

    C++ 獲取dll當(dāng)前路徑下所有文件

    本文主要介紹了C++ 獲取dll當(dāng)前路徑下所有文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • C++和java設(shè)計(jì)模式之單例模式

    C++和java設(shè)計(jì)模式之單例模式

    這篇文章主要為大家詳細(xì)介紹了C++和java設(shè)計(jì)模式之單例模式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字

    C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言代碼實(shí)現(xiàn)猜數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Qt下調(diào)用vlc庫(kù)實(shí)現(xiàn)RTSP拉流播放和截圖過(guò)程詳解

    Qt下調(diào)用vlc庫(kù)實(shí)現(xiàn)RTSP拉流播放和截圖過(guò)程詳解

    這篇文章主要為大家介紹了Qt下調(diào)用vlc庫(kù)實(shí)現(xiàn)RTSP拉流播放和截圖過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • C++實(shí)現(xiàn)二叉樹基本操作詳解

    C++實(shí)現(xiàn)二叉樹基本操作詳解

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)二叉樹基本操作,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • C語(yǔ)言運(yùn)算符優(yōu)先級(jí)列表(超詳細(xì))

    C語(yǔ)言運(yùn)算符優(yōu)先級(jí)列表(超詳細(xì))

    本篇文章是對(duì)C語(yǔ)言中運(yùn)算符的優(yōu)先級(jí)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Qt5+QMediaPlayer實(shí)現(xiàn)音樂(lè)播放器的示例代碼

    Qt5+QMediaPlayer實(shí)現(xiàn)音樂(lè)播放器的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何利用Qt5和QMediaPlayer實(shí)現(xiàn)簡(jiǎn)易的音樂(lè)播放器,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2022-12-12
  • C++11中多線程編程-std::async的深入講解

    C++11中多線程編程-std::async的深入講解

    這篇文章主要給大家介紹了關(guān)于C++11中多線程編程-std::async的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評(píng)論