一、C++中類型識別ios
(1)在面向對象中可能出現下面的狀況ide
@1:基類指針指向子類對象 Base *p = new child();函數
@2:基類引用成爲子類對象的別名 Base& r = *p;spa
--上面的base是基類,child是這個基類的子類,第一種狀況,因爲賦值兼容性的存在,父類指針是能夠指向子類對象的,可是咱們沒法經過父類指針來知道當前指針指向的是不是子類對象。指針
--可是這時咱們能夠說,指針p的靜態類型是Base*(指針指望的類型),指針p的動態類型是child(由於這時指針p指向的類型不是自己指針p所指望的類型,因此child叫指針p的動態類型)對象
--第二種狀況,Base&是r的靜態類型,由於r這個引用指望獲得的類型是Base這個父類,可是因爲賦值兼容性原則,此時r成爲了子類child所在堆空間的別名了,引用自己也沒有辦法肯定引用的到字符串
--底是父類對象仍是子類對象。因此child這個類型此時也是引用r的動態類型(由於和r自己想引用的類型不一樣)。string
(2)靜態類型:變量(對象)自己的類型叫作靜態類型。it
(3)動態類型:指針(引用)所指向對象的實際類型。io
void test(Base *b)
{
child *d = static_cast<child*>(b); //危險的轉換方式,若是b指針指向的子類對象,那就是徹底能夠的。
}
基類指針是否能夠強制類型轉換爲子類指針取決於動態類型。
二、C++中如何獲得對象的動態類型?
(1)解決方案1:利用多態
@1:在基類中定義虛函數返回具體的類型信息(返回字符串,字符串來表示當前的類型信息)
@2:全部的派生類都必須實現類型相關的虛函數
@3:每一個類中的類型虛函數都須要不一樣的實現
@4:咱們調用這個類對象的類型虛函數,就能夠知道當前類到底是子類仍是父類了。
例:
#include <iostream>
#include <string>
using namespace std;
/*
* 利用多態的方法,進行對象的動態類型識別,也就是區別判斷出,當前的父類指針指向的究竟是子類對象仍是父類對象。
*
*
*/
class Base
{
public:
virtual string type()
{
return "Base";
}
};
class child : public Base
{
public:
virtual string type() //子類重寫這個函數,到時用來判斷父類指針指向的究竟是父類對象仍是子類對象的
{
return "child";
}
void print()
{
cout << "I'm a child. " << endl;
}
};
void test(Base *b)
{
if ( b->type() == "child" )
{
child *c = static_cast<child*>(b);
c->print();
}
}
int main(void)
{
Base b;
child c;
test(&b);
test(&c);
return 0;
}
(2)多態解決方案的缺陷:
@1:必須從基類開始提供類型虛函數
@2:全部的派生類必須重寫類型虛函數
@3:每一個派生類的名字必須惟一
(3)C++提供了typeid關鍵字用與獲取類型信息,使用時要包含頭文件<typeinfo>
@1:typeid關鍵字返回對應參數的類型信息
@2:typeid返回一個type_info類對象,因此要包含頭文件typeinfo
@3:當typeid的參數爲NULL時將拋出異常
(4)typeid關鍵字的使用
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl; // 1
(5)typeid的注意事項
@1:當參數爲類型時:返回靜態類型信息(指望的類型)
@2:當參數爲變量時:
不存在虛函數表時:返回靜態類型信息
存在虛函數表時:返回動態類型信息(實際對象的類型)
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
/*
* 利用typeid,進行對象的動態類型識別,也就是區別判斷出,當前的父類指針指向的究竟是子類對象仍是父類對象。
*
*
*/
class Base
{
public:
virtual ~Base()
{
}
};
class child : public Base
{
public:
};
void test(Base *b)
{
const type_info& tb = typeid(*b);
cout << tb.name() << endl;
}
int main(void)
{
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tii == tiv) << endl;
Base b;
child c;
test(&b);
test(&c);
return 0;
}