c++ 有趣的動態(tài)轉換
緣起
最近,在項目代碼中看到一個非常神奇的類型轉換—— 類型A 的指針居然能動態(tài)轉換成另外一個完全沒有任何關系的類指針。這…… 完全顛覆了我的認知。
為了進一步了解這個神奇的操作,我特意模擬了項目代碼中的情形,一起來看看吧。
代碼簡介
BaseA 和 BaseB 是兩個基類,NewA 繼承自 BaseA,NewB 繼承自 BaseB。TestB() 會在堆上 new 一個 NewB 的對象,但是會強制轉換成 BaseA 類型的指針并返回(這個操作太逆天,大家一定不要在項目代碼中這么玩兒)。main() 函數(shù)中模擬使用和釋放。背景介紹完畢,看代碼。
測試代碼 1
#include "stdafx.h"
#include "stdlib.h"
class BaseA
{
public:
virtual void AA() = 0;
virtual ~BaseA() {};
};
class NewA : public BaseA
{
public:
~NewA() { printf(__FUNCTION__ "\n"); }
virtual void AA() override { printf(__FUNCTION__ "\n"); }
};
class BaseB
{
public:
virtual void BB() = 0;
virtual ~BaseB() {};
};
class NewB : public BaseB
{
public:
virtual ~NewB() { printf(__FUNCTION__ "\n"); }
virtual void BB() override { printf(__FUNCTION__ "\n"); }
};
BaseA* TestB()
{
NewB *pNewB = new NewB();
return (BaseA*)pNewB;
}
int _tmain(int argc, _TCHAR* argv[])
{
BaseA* pBaseA = TestB();
BaseB *pBaseB = (BaseB *)pBaseA;
delete(pBaseA);
system("pause");
return 0;
}
上面的代碼有什么問題嗎?運行結果是:一切正常。

but……
測試代碼 2
相對于 測試代碼1,測試代碼2 中調用了虛函數(shù),只改變了 main 中的調用部分。
int _tmain(int argc, _TCHAR* argv[])
{
BaseA* pBaseA = TestB();
BaseB *pBaseB = (BaseB *)pBaseA;
// added part: call virtual functions
pBaseA->AA();
pBaseB->BB();
delete(pBaseA);
system("pause");
return 0;
}
上面的代碼會輸出什么呢?

pBaseA->AA() 的輸出結果是 NewB::BB。有些“意外”,但是卻在情理之中。下一篇會比較詳細的剖析虛函數(shù)調用機制,知道運作及之后,再回過頭來看這個問題就很容易理解了!
測試代碼 3
相對于 測試代碼2,測試代碼 3 只為 BaseB 增加了一個名為 PerfectFunctionName() 的接口,并在子類NewB 中實現(xiàn)了這個接口。其它部分不變。這里只列出變化的部分。
#include "stdafx.h"
#include "stdlib.h"
class BaseB
{
public:
virtual void BB() = 0;
virtual void PerfectFunctionName() = 0; // Added part
virtual ~BaseB() {};
};
class NewB : public BaseB
{
public:
virtual ~NewB() { printf(__FUNCTION__ "\n"); }
virtual void BB() override { printf(__FUNCTION__ "\n"); }
virtual void PerfectFunctionName() override { printf(__FUNCTION__ "\n"); } // Added part
};
最新代碼運行結果會是什么樣的呢?

上圖是 32 位 debug 版程序運行時的輸出結果。終于報了異常!release 版運行后也會報異常!

從測試結果可知,這種做法在某些情況下確實可以正常運行,但是某些情況下會得到一些奇怪的結果,甚至會發(fā)生崩潰。這些現(xiàn)象背后的原因我想留到后面幾篇文章分析。感興趣的小伙伴兒可以手動測試并分析。
結論
永遠不要做這種危險的 SAO 操作!
以上就是c++ 動態(tài)轉換的詳細內容,更多關于c++ 動態(tài)轉換的資料請關注腳本之家其它相關文章!
相關文章
C++?Qt開發(fā)之運用QJSON模塊解析數(shù)據(jù)
JSON(JavaScript?Object?Notation)是一種輕量級的數(shù)據(jù)交換格式,它易于人閱讀和編寫,也易于機器解析和生成,本文主要介紹了Qt如何運用QJson組件的實現(xiàn)對JSON文本的靈活解析功能,需要的可以參考下2024-01-01
Qt如何實現(xiàn)輸入框@聯(lián)系人的@檢測的示例
本文主要介紹了Qt如何實現(xiàn)輸入框@聯(lián)系人的@檢測的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-08-08
C語言庫函數(shù)qsort及bsearch快速排序算法使用解析
這篇文章主要為大家介紹了C語言庫函數(shù)qsort及bsearch快速排序算法的使用示例解析2022-02-02

