溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

類型識(shí)別(五十四)

發(fā)布時(shí)間:2020-07-17 15:25:12 來(lái)源:網(wǎng)絡(luò) 閱讀:389 作者:上帝之子521 欄目:編程語(yǔ)言

        我們?cè)诿嫦驅(qū)ο笾锌赡軙?huì)出現(xiàn)這樣的情況:基類指針指向子類對(duì)象、基類引用成為子類對(duì)象的別名。如下

類型識(shí)別(五十四)

        靜態(tài)類型便指的是變量(對(duì)象)自身的類型,動(dòng)態(tài)類型是指指針(引用)所指向?qū)ο蟮膶?shí)際類型。基類指針是否可以強(qiáng)制類型轉(zhuǎn)換為子類指針取決于動(dòng)態(tài)類型!下面的這種轉(zhuǎn)換方式是危險(xiǎn)的

類型識(shí)別(五十四)

        那么我們?cè)?C++ 中如何得到動(dòng)態(tài)類型呢?解決方案便是利用多態(tài):1、在基類中定義虛函數(shù)返回具體的類型信息;2、所有的派生類都必須實(shí)現(xiàn)類型相關(guān)的虛函數(shù);3、每個(gè)類中的類型虛函數(shù)都需要不同的實(shí)現(xiàn)。

        下來(lái)我們就用代碼來(lái)分析

#include <iostream>
#include <string>

using namespace std;

class Base
{
public:
    virtual string type()
    {
        return "Base";
    }
};

class Derived : public Base
{
public:
    string type()
    {
        return "Derived";
    }
    
    void print()
    {
        cout << "I'm Derived." << endl;
    }
};

class Child : public Base
{
public:
    string type()
    {
        return "Child";
    }
};

void test(Base* b)
{
    if( b->type() == "Derived" )
    {
        Derived* d = static_cast<Derived*>(b);
        
        d->print();
    }
    
    cout << dynamic_cast<Derived*>(b) << endl;
}

int main()
{
    Base b;
    Derived d;
    Child c;
    
    test(&b);
    test(&d);
    test(&c);

    return 0;
}

        我們利用強(qiáng)制類型轉(zhuǎn)換的時(shí)候,首先得考慮指向的對(duì)象是不是和需要轉(zhuǎn)換的對(duì)象是一致的,如果是則進(jìn)行轉(zhuǎn)換。否則會(huì)翻車。我們看看編譯結(jié)果

類型識(shí)別(五十四)

        我們看到只輸出了 Derived 類。我們之前說(shuō)過(guò),在進(jìn)行繼承相關(guān)的轉(zhuǎn)換時(shí),最好用 dynamic_cast 關(guān)鍵字,下面我們將 test 函數(shù)中的注釋去掉,再來(lái)編譯看看

類型識(shí)別(五十四)

        我們看到成功實(shí)現(xiàn)轉(zhuǎn)換的打印出了地址,沒成功的都為 0 了。我們利用多態(tài)成功的實(shí)現(xiàn)了動(dòng)態(tài)類型的識(shí)別。但是有點(diǎn)小缺陷,就是必須從基類開始通過(guò)類型虛函數(shù),所有的派生類都必須重寫類型虛函數(shù),每個(gè)派生類的類型名必須唯一。

        那么在 C++ 中是通過(guò)了類型識(shí)別關(guān)鍵字的,typeid 關(guān)鍵字用于獲取類型信息。typeid 關(guān)鍵字返回對(duì)應(yīng)參數(shù)的類型信息,它返回一個(gè) type_info 類對(duì)象,當(dāng) typeid 的參數(shù)為 NULL 時(shí)將拋出異常。typeid 的注意事項(xiàng):當(dāng)參數(shù)為類型時(shí),返回靜態(tài)類型信息;當(dāng)參數(shù)為變量時(shí),不存在虛函數(shù)表則返回靜態(tài)類型信息,存在虛函數(shù)表則返回動(dòng)態(tài)類型信息。

        下來(lái)還是以代碼為例來(lái)進(jìn)行分析

#include <iostream>
#include <string>
#include <typeinfo>

using namespace std;

class Base
{
public:
    virtual ~Base()
    {
    }
};

class Derived : public Base
{
public:
    void print()
    {
        cout << "I'm Derived." << endl;
    }
};

class Child : public Base
{
public:
    string type()
    {
        return "Child";
    }
};

void test(Base* b)
{
    const type_info& tb = typeid(*b);
    
    cout << tb.name() << endl;
}

int main()
{
    int i = 0;
    
    const type_info& tiv = typeid(i);
    const type_info& tvv = typeid(int);
    
    cout << (tiv == tvv) << endl;
    
    cout << endl;
    
    Base b;
    Derived d;
    
    test(&b);
    test(&d);

    return 0;
}

        我們打印 i 和 int 的信息應(yīng)該是一致的,所以應(yīng)該打印出 1。來(lái)看看編譯結(jié)果

類型識(shí)別(五十四)

        我們來(lái)看看如果不定義虛函數(shù)呢,看看編譯結(jié)果

類型識(shí)別(五十四)

        我們看到如果定義了虛函數(shù)的話,打印的便是動(dòng)態(tài)類型的;沒定義的話,打印的便是靜態(tài)類型的。下來(lái)我們?cè)儆?BCC 編譯器來(lái)看看結(jié)果

類型識(shí)別(五十四)

        我們看到 typeid 關(guān)鍵字在不同的編譯器上打印的行為是有點(diǎn)區(qū)別的。通過(guò)對(duì)類型識(shí)別的學(xué)習(xí),總結(jié)如下:1、C++ 中有靜態(tài)類型和動(dòng)態(tài)類型的概念;2、利用多態(tài)能夠?qū)崿F(xiàn)對(duì)象的動(dòng)態(tài)類型識(shí)別;3、typeid 是專用于類型識(shí)別的關(guān)鍵字,它能夠返回對(duì)象的動(dòng)態(tài)類類型信息。


        歡迎大家一起來(lái)學(xué)習(xí) C++ 語(yǔ)言,可以加我QQ:243343083

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI