![](/img/trans.png)
[英]error C2440: 'static_cast' : cannot convert from 'void (__thiscall Visualizza::* )(char [])' to 'AFX_PMSG'
[英]C2440 static_cast cannot convert from base class to derived class
我試圖理解為什么使用指針從基類強制轉換為派生類的編譯效果很好,但是使用非指針對象進行強制轉換會產生錯誤C2440。
下面有一個基類ThreadedMessage
,它由類GPSMessage
繼承。
struct ThreadedMessage
{
ThreadedMessage()
: m_Type(0), m_ID(0)
{ }
ThreadedMessage(uint Type, uint ID = 0) :
m_Type(Type), m_ID(ID)
{ }
uint m_Type;
uint m_ID;
};
struct GPSMessage : public ThreadedMessage
{
GPSMessage()
: ThreadedMessage()
{ }
GPSMessage(double lat, double lon)
: ThreadedMessage(1), m_lat(lat), m_lon(lon)
{ }
double m_lat;
double m_lon;
};
在myFunction
我嘗試從基類myFunction
轉換為派生類。
void myFunction(const ThreadedMessage& msg)
{
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
}
對myFunction()
的調用如下所示:
GPSMessage msg(21.123, 12.321);
myFunction(msg);
當我編譯時,指針的轉換可以正常編譯,但是非指針的轉換失敗,並出現以下錯誤:
錯誤C2440:“ static_cast”:無法從“ const ThreadedMessage”轉換為“ const GPSMessage”沒有構造函數可以采用源類型,或者構造函數重載解析度不明確
為什么我不能使用非指針變量將基類轉換為派生類?
編譯器為MS VS 2008 C ++。
是的,我看過其他類似的SO問題,但我閱讀的問題似乎無法回答我的問題。
這兩個角色具有不同的含義。
第一個演員:
const GPSMessage* message = static_cast<const GPSMessage*>(&msg); // Compiles fine
這意味着msg
實際上是GPSMessage
(或派生的)對象。 您要求編譯器將msg
作為GPSMessage
威脅。 不會創建新對象, message
將指向msg
。 如果msg
實際上不是GPSMessage
(或派生的),則此GPSMessage
Undefined Behavior。
順便說一句,下面的演員表具有相同的含義(鑄造參考):
const GPSMessage& message = static_cast<const GPSMessage&>(msg); // same meaning, which results in a reference instead of a pointer
關於第二個演員表:
const GPSMessage message1 = static_cast<const GPSMessage>(msg); // Error C2440
這意味着您將創建一個新對象, message1
msg
message1
。 您應該提供一種使這種轉換成為可能的方法。 例如,您應該為GPSMessage
創建一個具有ThreadedMessage
參數的構造函數:
struct GPSMessage {
GPSMessage(const ThreadedMessage &); // needed constructor
};
或創建ThreadedMessage
到GPSMessage
的轉換運算符:
struct ThreadedMessage {
operator GPSMessage(); // conversion operator
};
在函數中,編譯器僅知道msg
是對ThreadedMessage
的引用,而不知道在函數內部作為參數實際傳遞了什么。
想想如果傳遞對實際 ThreadedMessage
對象的引用會發生什么情況? 還是從其他繼承的類對另一個對象的引用?
要從ThreadedMessage
對象轉換為GPSMessage
對象,需要進行轉換,並且這種轉換是不可能的( ThreadedMessage
類沒有轉換運算符,而GPSMessage
沒有合適的構造函數)。
唯一的解決方案是將指針或引用轉換為另一個指針或引用。 就像您在指針示例中所做的那樣,或通過例如
const GPSMessage& message1 = static_cast<const GPSMessage&>(msg);
如果您確實要GPSMessage
轉換為GPSMessage
對象 ,而不是引用或指針,那么最好的解決方案是使用轉換構造函數:
class GPSMessage : public ThreadedMessage
{
public:
...
explicit GPSMessage(const ThreadedMessage& tm)
: GPSMessage(static_cast<const GPSMessage&>(tm)) // Invoke copy-constructor
{}
...
};
使用copy-constructor很好,但是它要求tm
參數確實是對GPSMessage
對象的引用。 否則無效。
另一個解決方案是使類具有多態性 (通過將析構函數設為virtual
來dynamic_cast
),並使用dynamic_cast
指向指針。 如果結果為空指針,則msg
不是GPSMessage
開頭。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.