虚拟函数的静态决议 和 RTTI 小例子
一:先說虛擬函數(shù)的靜態(tài)決議(Static Resolution)
在兩種情況下,虛擬函數(shù)機制不會出現(xiàn)預期行為:1、在基類的constructor和destructor內;2、當我們使用的是基類的對象,而非基類對象的pointer 或 reference時。
上述第二種情況很好理解,第二種情況是C++多態(tài)機制的重要概念。第一種情況其實也很簡單,但我才剛開始學習C++,怕以后自己會不小心把一些虛函數(shù)寫在constructor 或 destructor里,固寫此文章記錄一下,下面給出第一種情況的解釋:
-----------------摘抄Essential C++解釋開始-----------------
當我們構造派生類對象時,基類的constructor會先被調用。如果在基類的constructor中調用某個虛擬函數(shù),會發(fā)生什么事?調用的應該是派生類所定義的那一份嗎?
問題出在此刻派生類中的data member尚未初始化。如果此時調用派生類的那一份虛擬函數(shù),它便有可能取用未經初始化的data members,這可不是一件好事。
基于這個理由,在基類的constructor中,派生類的虛擬函數(shù)絕對不會被調用。同理,如果在基類的destructor中調用虛擬函數(shù),此規(guī)則同樣成立。
-----------------摘抄Essential C++解釋結束-----------------
舉例:
基類代碼
1 #pragma once
2 #include <typeinfo>
3 #include <iostream>
4 class num_sequence
5 {
6 public:
7 num_sequence(void);
8 virtual const char* what_am_i() const;
9 virtual void display() const { std::cout << "Based decontroctor" << std::endl; }
10 virtual ~num_sequence(void) { display(); }
11 };
派生類代碼
1 #pragma once
2 #include "num_sequence.h"
3
4 class Fibonacci :
5 public num_sequence
6 {
7 public:
8 Fibonacci(void);
9 virtual void display() const { std::cout << "Drived destructor" << std::endl; }
10 ~Fibonacci(void) { display(); };
11 void testTypeId() { std::cout << "testTypeIdFunction" << std::endl; }
12 };
然后在main里測試:
Fibonacci fib;
num_sequence *ps = &fib;
輸出的結果是:
Derived destructor
Based destructor
請按任意鍵繼續(xù). . .
即:分別調用子類和基類的析構函數(shù)(調用基類的析構函數(shù)時,基類析構函數(shù)里的display()函數(shù)沒有動態(tài)執(zhí)行子類的display())
?
二:RTTI
基類num_sequence.cpp中加入
inline const char* num_sequence::what_am_i() const{
return typeid( *this ).name();
}
主main程序里面:
1 Fibonacci fib;
2 num_sequence *ps = &fib;
3
4 if ( typeid(*ps) == typeid(Fibonacci) )
5 {
6 ps->Fibonacci::testTypeId(); // 錯誤
7 ps->testTypeId();// 錯誤
8 if ( Fibonacci *pf = dynamic_cast<Fibonacci*> (ps) )
9 {
10 pf->testTypeId();
11 }
12 }
Line6、Line7錯誤,這里ps并不"知道"它所尋址的對象實際上是什么型別--縱使我們知道,typeid及虛擬函數(shù)機制也知道。。
為了調用Fibonacci所定義的testTypeId(),我們必須指示編譯器,將ps的型別轉換為Fibonacci指針。
1、static_cast可以轉換:Fibonacci *pf = static_cast<Fibonacci*>( ps );
但存在危險,因為編譯器無法確認我們所進行的轉換操作是否完全正確。
2、dynamic_cast:這是一個RTTI運算法,會進行執(zhí)行期檢驗操作,檢驗ps所指對象是否屬于Fibonacci類。如果是,轉換操作便會發(fā)生,于是pf便指向該Fibonacci對象。如果不是,dynamic_cast運算符返回0。
轉載于:https://www.cnblogs.com/ziyoudefeng/archive/2012/03/20/2407907.html
總結
以上是生活随笔為你收集整理的虚拟函数的静态决议 和 RTTI 小例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态规划 - 装配线调度问题
- 下一篇: kk