39、不一樣的C++系列--型別識別
阿新 • • 發佈:2019-02-16
型別識別
- 在面向物件中可能出現下面的情況
- 基類指標指向子類物件
- 基類引用成為子類物件的別名
//Base* Base& 靜態型別
//Derived 動態型別
Base* p = new Derived();
Base& r = *p;
型別區別:
- 靜態型別
- 變數(物件)自身的型別
- 動態型別
- 指標(引用)所指向物件的實際型別
void test(Base* b)
{
//危險的轉換方式
Derived* d = static_cast<Derived *>(b);
}
在上述程式碼中,基類指標是否可以強制型別轉換為子類指標取決於動態型別!
在C++中是利用多型來得到動態型別
- 在基類中定義虛擬函式返回具體的型別資訊
- 所有的派生類都必須實現型別相關的虛擬函式
- 每個類中的型別虛擬函式都需要不同的實現
這裡舉個例子:
#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 printf()
{
cout << "I'm a Derived." << endl;
}
};
//定義子類 繼承基類
class Child : public Base
{
public:
string type()
{
return "Child";
}
};
void test(Base* b)
{
/* 危險的轉換方式 */
// Derived* d = static_cast<Derived*>(b);
//這裡最安全的辦法就是使用類成員函式來返回型別,然後來判斷
if( b->type() == "Derived" )
{
Derived* d = static_cast<Derived*>(b);
d->printf();
}
// cout << dynamic_cast<Derived*>(b) << endl;
}
int main(int argc, char *argv[])
{
Base b;
Derived d;
Child c;
test(&b);
test(&d);
test(&c);
return 0;
}
執行結果為:
I'm a Derived.
上述的解決方案存在一些缺陷:
- 必須從基類開始提供型別虛擬函式
- 所有的派生類都必須重寫型別虛擬函式
- 每個派生類的型別名必須唯一
那有沒有另外一種可以完善這些缺點的方案呢?有的,這裡我們來學習一個新的知識點:
- C++提供了typeid關鍵字用於獲取型別資訊
- typeid關鍵字返回對應引數的型別資訊
- typeid返回一個type_info類物件
- 當typeid的引數為NULL時將丟擲異常
typeid
關鍵字的使用
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl;
- typeid 的注意事項
- 當引數為型別時:返回靜態型別資訊
- 當引數為變數時:
- 不存在虛擬函式表 —- 返回靜態型別資訊
- 存在虛擬函式表 —- 返回動態型別資訊
使用示例:
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
//定義基類
class Base
{
public:
//解構函式為虛擬函式
virtual ~Base()
{
}
};
class Derived : public Base
{
public:
void printf()
{
cout << "I'm a Derived." << endl;
}
};
void test(Base* b)
{
const type_info& tb = typeid(*b);
//tb為type_info類,使用name成員函式可以得到型別名稱
cout << tb.name() << endl;
}
int main(int argc, char *argv[])
{
int i = 0;
//這裡使用typeid來獲取型別
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl;
Base b;
Derived d;
test(&b);
test(&d);
return 0;
}
輸出結果為:
1
4Base
7Derived