欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

C++語(yǔ)言學(xué)習(xí)(十九)——C++類型識(shí)別-創(chuàng)新互聯(lián)

C++語(yǔ)言學(xué)習(xí)(十九)——C++類型識(shí)別

一、C++類型識(shí)別簡(jiǎn)介

1、C++類型識(shí)別簡(jiǎn)介

C++是靜態(tài)類型語(yǔ)言,其數(shù)據(jù)類型是在編譯期就確定的,不能在運(yùn)行時(shí)更改。
C++語(yǔ)言中,靜態(tài)類型是對(duì)象自身的類型,動(dòng)態(tài)類型是指針(引用)所指向?qū)ο蟮膶?shí)際類型。
RTTI(Run-Time Type Information)即運(yùn)行時(shí)類型識(shí)別,C++通過(guò)RTTI實(shí)現(xiàn)對(duì)多態(tài)的支持。
為了支持RTTI,C++提供了一個(gè)type_info類和typeid與dynamic_cast兩個(gè)關(guān)鍵字。

創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站建設(shè)、做網(wǎng)站與策劃設(shè)計(jì),東海網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:東海等地區(qū)。東海做網(wǎng)站價(jià)格咨詢:18982081108

2、type_info結(jié)構(gòu)體

type_info :
存儲(chǔ)特點(diǎn)類型的相關(guān)信息,常用來(lái)比較對(duì)象類型,type_info類的具體內(nèi)容由編譯器實(shí)現(xiàn)來(lái)決定。其聲明如下:

class type_info {
public:
    virtual ~type_info();
    bool operator== (const type_info& rhs) const;
    bool operator!= (const type_info& rhs) const;
    bool before (const type_info& rhs) const;
    const char* name() const;
private:
    type_info (const type_info& rhs);
    type_info& operator= (const type_info& rhs);
};

type_info的構(gòu)造函數(shù)和賦值操作符為私有,因此,程序中創(chuàng)建type_info對(duì)象的唯一方法是使用typeid操作符。C++標(biāo)準(zhǔn)只是告訴編譯器需要實(shí)現(xiàn)type_info::name函數(shù),但不同的編譯器實(shí)現(xiàn)各不相同,因此typeid(int).name()不同編譯器編譯運(yùn)行后輸出不一樣。

3、typeid關(guān)鍵字

typeid:
typeid語(yǔ)法規(guī)則如下:typeid(expr);
typeid表達(dá)式返回type_info類型,expr可以是各種類型名,對(duì)象和內(nèi)置基本數(shù)據(jù)類型的實(shí)例、指針或者引用。當(dāng)作用于指針和引用時(shí),將返回實(shí)際指向?qū)ο蟮念愋托畔ⅰ?br/>如果表達(dá)式的類型是類類型且至少包含有一個(gè)虛函數(shù),則typeid操作符返回表達(dá)式的動(dòng)態(tài)類型,需要在運(yùn)行時(shí)確定;否則,typeid操作符返回表達(dá)式的靜態(tài)類型,在編譯時(shí)就可以確定。
當(dāng)把typeid作用于指針的解引用p時(shí),若指針p為0,則:如果p指向的類型是帶虛函數(shù)的類類型,則typeid(p)在運(yùn)行時(shí)拋出一個(gè)bad_typeid異常;否則,typeid(*p)的結(jié)果與p的值是不相關(guān)的,在編譯時(shí)就可以確定。

4、dynamic_cast關(guān)鍵字

dynamic_cast:
動(dòng)態(tài)類型轉(zhuǎn)換,運(yùn)行時(shí)類型安全檢查。dynamic_cast會(huì)檢查待轉(zhuǎn)換的源對(duì)象是否真的可以轉(zhuǎn)換成目標(biāo)類型,這種檢查不是語(yǔ)法上的,而是真實(shí)情況的。許多編譯器都是通過(guò)vtable找到對(duì)象的RTTI信息的,如果基類沒(méi)有虛方法,也就無(wú)法判斷一個(gè)基類指針變量所指對(duì)象的真實(shí)類型。
dynamic_cast將一個(gè)指向基類的指針轉(zhuǎn)換為一個(gè)指向派生類的指針,如果不能正確轉(zhuǎn)換,則返回空指針。
C++語(yǔ)言提供了typeid關(guān)鍵字用于獲取類型信息,typeid關(guān)鍵字返回對(duì)應(yīng)參數(shù)的類型信息。typeid返回一個(gè)type_info類對(duì)象,當(dāng)typeid的參數(shù)為NULL時(shí)將拋出異常。typeid的參數(shù)既可以時(shí)類型也可以是變量,當(dāng)參數(shù)為類型,返回靜態(tài)類型信息;當(dāng)參數(shù)為變量,如果不存在虛函數(shù)表,返回靜態(tài)類型信息,如果存在虛函數(shù)表,返回動(dòng)態(tài)類型信息。
typeid操作符的返回結(jié)果是名為type_info的標(biāo)準(zhǔn)庫(kù)類型的對(duì)象的引用。
typeid在不同C++編譯器實(shí)現(xiàn)是不同的。

RTTI(Run-Time Type Identification,運(yùn)行時(shí)類型識(shí)別)

二、C++類型轉(zhuǎn)換

C++類型轉(zhuǎn)換分為向上類型轉(zhuǎn)換和向下類型轉(zhuǎn)換。

1、向上類型轉(zhuǎn)換

C++語(yǔ)言中,向上類型轉(zhuǎn)換描述的是子類向基類的強(qiáng)制類型轉(zhuǎn)換,是一種隱式類型轉(zhuǎn)換。在向上類型轉(zhuǎn)換過(guò)程中,覆蓋方法和子類對(duì)象數(shù)據(jù)丟失的現(xiàn)象稱為切割。

#include <iostream>

using namespace std;

class Base
{
public:
    Base(int value = 0)
    {
        data = value;
    }
    virtual void print()
    {
        cout << "Base::print data = " << data << endl;
    }
protected:
    int data;
};

class Derived : public Base
{
public:
    Derived(int value = 0)
    {
        data = value;
    }
    virtual void print()
    {
        cout << "Derived print data = " << data << endl;
    }
protected:
    int data;
};

int main(int argc, char *argv[])
{
    Derived d(100);
    //將子類向上轉(zhuǎn)型為基類
    Base b = d;//直接賦值,產(chǎn)生切割
    b.print();//Base::print data = 0

    Base& rb = d;//引用賦值,不產(chǎn)生切割
    rb.print();//Derived print data = 100

    Base* pb = &d;//指針賦值,不產(chǎn)生切割
    pb->print();//Derived print data = 100

    //Derived* dp = pb;//error,不允許隱式向下轉(zhuǎn)型
    return 0;
}

在向上強(qiáng)制轉(zhuǎn)換過(guò)程中,使用指針和引用不會(huì)造成切割,而使用直接賦值會(huì)造成切割。

2、向下類型轉(zhuǎn)換

C++語(yǔ)言中,向下類型轉(zhuǎn)換描述的是基類向子類的強(qiáng)制類型轉(zhuǎn)換,使用dynamic_cast進(jìn)行向下強(qiáng)制類型轉(zhuǎn)換。dynamic_cast會(huì)在運(yùn)行時(shí)進(jìn)行類型檢查。如果向下轉(zhuǎn)型是安全的(如果基類指針或者引用實(shí)際指向一個(gè)派生類的對(duì)象),dynamic_cast會(huì)返回類型轉(zhuǎn)換后的指針。如果向下轉(zhuǎn)型不安全(即基類指針或者引用沒(méi)有指向一個(gè)派生類的對(duì)象),dynamic_cast返回空指針。?使用dynamic_cast時(shí),類中必須定義虛函數(shù)。

#include <iostream>

using namespace std;

class Base
{
public:
    Base(int value = 0)
    {
        data = value;
    }
    virtual void print()
    {
        cout << "Base::print data = " << data << endl;
    }
protected:
    int data;
};

class Derived : public Base
{
public:
    Derived(int value = 0)
    {
        data = value;
    }
    virtual void print()
    {
        cout << "Derived print data = " << data << endl;
    }
protected:
    int data;
};

int main(int argc, char *argv[])
{
    //指針
    Base* bp1 = new Base(101);
    Derived* dp11 = static_cast<Derived*>(bp1);
    cout << "Base" << endl;
    cout << bp1 << endl;
    cout << dp11<< endl;
    dp11->print();//Base::print data = 101
    Derived* dp12 = dynamic_cast<Derived*>(bp1);
    cout << dp12 << endl;//0,向下轉(zhuǎn)型失敗
    if(dp12 != NULL)
    {
        dp12->print();
    }

    Base* bp2 = new Derived(102);
    Derived* dp21 = static_cast<Derived*>(bp2);
    cout << "Derived" << endl;
    cout << bp2 << endl;
    cout << dp21<< endl;
    dp21->print();//Derived print data = 102
    Derived* dp22 = dynamic_cast<Derived*>(bp2);
    cout << dp22 << endl;//向下轉(zhuǎn)型成功
    if(dp22 != NULL)
    {
        dp22->print();//Derived print data = 102
    }
    //引用
    Base b1(10);
    Derived& rd11 = static_cast<Derived&>(b1);
    rd11.print();//Base::print data = 10
    //Derived& rd12 = dynamic_cast<Derived&>(b1);//exception
    Derived b2(10);
    Derived& rd21 = static_cast<Derived&>(b2);
    rd21.print();//Derived print data = 10
    Derived& rd22 = dynamic_cast<Derived&>(b2);
    rd22.print();//Derived print data = 10

    return 0;
}

上述代碼中,如果指針、引用實(shí)際指向的對(duì)象為派生類對(duì)象,使用static_cast、dynamic_cast轉(zhuǎn)換都是安全的;如果指針、引用實(shí)際指向的對(duì)象為基類對(duì)象,使用dynamic_cast會(huì)返回NULL指針或拋出異常,使用static_cast關(guān)鍵字返回執(zhí)行基類對(duì)象的指針或引用,不能訪問(wèn)派生類的覆蓋方法與成員。

3、多繼承時(shí)的向下轉(zhuǎn)型

#include <iostream>

using namespace std;

class BaseA
{
public:
    BaseA(int value = 0)
    {
        data = value;
    }
    virtual void printA()
    {
        cout << "BaseA::print data = " << data << endl;
    }
protected:
    int data;
};

class BaseB
{
public:
    BaseB(int value = 0)
    {
        data = value;
    }
    virtual void printB()
    {
        cout << "BaseB::print data = " << data << endl;
    }
protected:
    int data;
};

class Derived : public BaseA, public BaseB
{
public:
    Derived(int value = 0)
    {
        data = value;
    }
    virtual void printA()
    {
        cout << "Derived printA data = " << data << endl;
    }
    virtual void printB()
    {
        cout << "Derived printB data = " << data << endl;
    }
protected:
    int data;
};

int main(int argc, char *argv[])
{
    //BaseA
    cout << "BaseA" << endl;
    BaseA* bpa = new BaseA(10);
    cout << bpa << endl;
    Derived* pd1 = static_cast<Derived*>(bpa);
    cout << pd1 << endl;
    pd1->printA();//BaseB::print data 10
    //pd1->printB();//exception,實(shí)際指向BaseA對(duì)象,沒(méi)有printB方法
    Derived* pd2 = dynamic_cast<Derived*>(bpa);
    cout << pd2 << endl;//0,向下轉(zhuǎn)型失敗
    if(pd2 != NULL)
    {
        pd2->printA();
        pd2->printB();
    }

    //BaseB
    cout << "BaseB" << endl;
    BaseB* bpb = new BaseB(10);
    cout << bpb << endl;
    //pd3指向bpb前8字節(jié)的地址
    Derived* pd3 = static_cast<Derived*>(bpb);
    cout << pd3 << endl;
    //pd3->printA();//exception
    //pd3->printB();//exception
    Derived* pd4 = dynamic_cast<Derived*>(bpb);
    cout << pd4 << endl;//0,向下轉(zhuǎn)型失敗
    if(pd4 != NULL)
    {
        pd4->printA();
        pd4->printB();
    }

    cout << "Derived" << endl;
    BaseA* bpd = new Derived(101);
    cout << bpd << endl;
    Derived* pd5 = static_cast<Derived*>(bpd);
    cout << pd5 << endl;
    pd5->printA();//Derived printA data = 101
    pd5->printB();//Derived printB data = 101
    Derived* pd6 = dynamic_cast<Derived*>(bpd);
    cout << pd6 << endl;
    if(pd6 != NULL)
    {
        pd6->printA();//Derived printA data = 101
        pd6->printB();//Derived printB data = 101
    }
    BaseA* pa = static_cast<BaseA*>(bpd);
    pa->printA();
    //BaseB* pb = static_cast<BaseB*>(bpd);//error,
    BaseB* pb = dynamic_cast<BaseB*>(bpd);//正確,
    pb->printB();

    cout << "Derived+" << endl;
    Derived* dpd = new Derived(102);
    cout << dpd << endl;
    BaseA* dpa = static_cast<BaseA*>(dpd);
    cout << dpa << endl;
    dpa->printA();
    BaseB* dpb1 = static_cast<BaseB*>(dpd);//
    cout << dpb1 << endl;
    dpb1->printB();
    BaseB* dpb2 = dynamic_cast<BaseB*>(dpd);//
    cout << dpb2 << endl;
    dpb2->printB();

    return 0;
}

上述代碼中,bpa指針指向BaseA對(duì)象,使用static_cast關(guān)鍵字對(duì)bpa進(jìn)行向下轉(zhuǎn)型為Derived指針對(duì)象時(shí),返回bpa的值,由于實(shí)際指向BaseA對(duì)象,因此對(duì)BaseB方法時(shí)會(huì)導(dǎo)致異常;使用dynamic_cast關(guān)鍵字對(duì)bpa進(jìn)行向下轉(zhuǎn)型時(shí),轉(zhuǎn)型失敗,返回NULL。
bpb指針實(shí)際指向BaseB對(duì)象,使用static_cast關(guān)鍵字對(duì)bpb進(jìn)行向下轉(zhuǎn)型為Derived指針對(duì)象時(shí),返回bpb地址的-8字節(jié)的地址,該地值是一個(gè)不合法的Derived對(duì)象地址,因此對(duì)該地址調(diào)用BaseA、BaseB類的方法時(shí)會(huì)導(dǎo)致異常;使用dynamic_cast關(guān)鍵字對(duì)bpa進(jìn)行向下轉(zhuǎn)型時(shí),轉(zhuǎn)型失敗,返回NULL。
bpd指針實(shí)際指向Derived對(duì)象,使用static_cast關(guān)鍵字對(duì)bpd進(jìn)行向下轉(zhuǎn)型為Derived指針對(duì)象時(shí),返回bpd的值,可以合法調(diào)用BaseA、BaseB類的方法;使用dynamic_cast關(guān)鍵字對(duì)bpd進(jìn)行向下轉(zhuǎn)型時(shí),返回bpd的值,可以合法調(diào)用BaseA、BaseB類的方法。如果使用static_cast關(guān)鍵字將BaseA類型指針bpd轉(zhuǎn)型為BaseB指針時(shí),C++編譯器報(bào)錯(cuò);必須使用dynamic_cast關(guān)鍵字,dynamic_cast會(huì)在運(yùn)行時(shí)對(duì)指針進(jìn)行調(diào)整。
Derived類型的dpd指針指向Derived對(duì)象,使用static_cast關(guān)鍵字和dynamic_cast關(guān)鍵字都可以進(jìn)行向上轉(zhuǎn)型。

三、C++內(nèi)省機(jī)制

所謂內(nèi)省是指面向?qū)ο笳Z(yǔ)言的一種在運(yùn)行期間查詢對(duì)象信息的能力, 比如如果語(yǔ)言具有運(yùn)行期間檢查對(duì)象型別的能力,那么語(yǔ)言是型別內(nèi)?。╰ype intropection)的,型別內(nèi)省可以用來(lái)實(shí)施多態(tài)。
C++的內(nèi)省比較有限,僅支持型別內(nèi)省, C++的型別內(nèi)省是通過(guò)運(yùn)行時(shí)類型識(shí)別(RTTI)(Run-Time Type Information)中的typeid?以及dynamic_case關(guān)鍵字來(lái)實(shí)現(xiàn)的。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

文章標(biāo)題:C++語(yǔ)言學(xué)習(xí)(十九)——C++類型識(shí)別-創(chuàng)新互聯(lián)
網(wǎng)頁(yè)網(wǎng)址:http://chinadenli.net/article10/dhjpdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站、靜態(tài)網(wǎng)站、網(wǎng)站制作、網(wǎng)站內(nèi)鏈、全網(wǎng)營(yíng)銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷型網(wǎng)站建設(shè)