第66課-C++中的型別識別
阿新 • • 發佈:2018-12-12
一、型別識別
在面向物件中可能出現下面的情況
- 基類指標指向子類物件
- 基類引用成為子類物件的別名
- 靜態型別——變數(物件)自身的型別
- 動態型別——指標(引用)所指向物件的實際型別
void test(Base* b){
//危險的轉換方式
Derived* d = static_cast<Derived*>(b);
}
基類指標是否可以強制型別轉換為子類指標取決於動態型別!
二、動態型別識別
解決方案——利用多型
- 在基類中定義虛擬函式返回具體的型別資訊
- 所有的派生類都必須實現型別相關的虛擬函式
- 每個類中的型別虛擬函式都需要不同的實現
程式設計實驗:動態型別識別
#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 "Chlid";
}
};
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(){
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;
//列印結果為1
typeid
的注意事項
- 當引數為型別時:返回靜態型別資訊
- 當引數為變數時:
- 不存在虛擬函式表——返回靜態型別資訊
- 存在虛擬函式表——返回動態型別資訊
程式設計實驗: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 Derive." << endl;
}
};
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& tii = typeid(int);
cout << (tiv == tii) << endl;
Base b;
Derived d;
test(&b);
test(&d);
return 0;
}
列印結果:
1
4Base
7Derived //因為存在虛擬函式,此時返回動態型別
四、總結
- C++中有靜態型別和動態型別的概念
- 利用多型能夠實現物件的動態型別識別
typeid
是專用於型別識別的關鍵字typeid
能夠返回物件的動態型別資訊