[英]Why does static_cast require pointers or references?
最近,我不得不使用static_cast將父類強制轉換為子類,因為我知道對象實例就是該子類。 我基於if條件知道這一點。
像這樣:
parent* foo;
child* bar;
if(foo is instance of child class)
bar = static_cast<child*>(foo)
我的問題是:為什么static_cast總是需要指針? 當我嘗試使用非指針變量時,這不起作用。 原始數據類型似乎是一個例外。
這是因為每個指針都可以轉換為void *嗎? 那是static_cast的工作方式嗎?
編輯:我忘了提及它與引用一起使用。 因此,當前提出的問題是錯誤的。 將問題重新定義為“為什么static_cast為什么需要指針或引用?”
為什么static_cast總是需要指針?
運算符static_cast
不需要指針,也不需要引用。
C ++標准n3337§5.2.9 / 4:
否則, 如果聲明
T t(e)
,則可以使用static_cast<T>(e)
形式的static_cast<T>(e)
將表達式e顯式轉換為T類型。 對於某些發明的臨時變量t
(8.5), 其格式正確 。 這種顯式轉換的效果與執行聲明和初始化,然后將臨時變量用作轉換結果的效果相同。 當且僅當初始化將其用作glvalue時,才將表達式e用作glvalue。
parent* foo;
child* bar;
if(foo is instance of child class)
bar = static_cast<child*>(foo)
當我嘗試使用非指針變量時,這不起作用。
例如? 您如何嘗試的? 如果你的意思是
child c;
parent p = static_cast<parent>( c);
然后這稱為切片 ,這意味着p將僅從c中獲取來自父類的數據(由於父子添加到派生的父數據中,父類的對象又如何接收子部分?)。
原因是:否,它可以是指針或引用。 這與以下問題有關:
struct Base
{
};
struct Derived : public Base
{
int A;
};
//sizeof(Base)==0
//sizeof(Derived)==4
Base B;
Derived X;
X.A = 10;
B=X;//what happens to Derived::A? There is no space to put it. This is called slicing.
基本上,您不能在不冒切片風險的情況下,通過派生類對基類進行實例化。 但是引用/指針是另一回事。 在這種情況下,您只是在解釋如何解釋所指向的內存。 在這種情況下,靜態投射實際上不執行任何操作! 由於C ++類的布局方式(有意地),從基類繼承的所有內容都具有從0偏移量到sizeof(Base)的相同內存布局。 只有在那之后,您才添加派生的東西。
為什么static_cast總是需要指針?
好吧,並非總是如此。 如您所指出的,以下是可能的:
int i = static_cast<int>(3.14);
static_cast
也可以用於在引用之間進行轉換,就像使用指針一樣。
但是,您必須考慮以下因素:在兩種類型之間進行轉換時,您可能會丟失信息。 假設您有一個Animal
類,另一個是Dog
類,它恰好繼承自它。 這是什么意思?
Dog d;
Animal a = static_cast<Animal>(d);
您是用Dog
創建Animal
的,但是Dog
的特定信息將被丟棄。 這稱為切片 。
指針之間的轉換通常只涉及重新解釋內存。 基礎對象保持不變。
本質上, static_cast<>
總是創建帶有尖括號之間提供的類型的新內容。 考慮:
class base { int x; };
class derived: public base { int y; };
現在,以下代碼將無法編譯:
base *b;
derived *d = &static_cast<derived>(*b); // wrong
原因很簡單:此代碼嘗試創建derived
新實例,並將base
傳遞給其構造函數。 如果derived
有該構造函數,它將進行編譯。 例如:
class derived: public base
{
int y;
derived(const base &){}
};
但是現在您有了一個臨時目錄,該臨時目錄將立即被刪除。
顯然,您不想在這里創建新的derived
實例,但是要到達派生實例,您的基礎就是其中的一部分。 在執行轉換時,您需要創建對derived
的引用或指針,而不是它的全新實例。 以下將起作用:
derived d;
base *bp = &d;
base &br = d;
derived &dr = static_cast<derived &>(br);
derived *dp = static_cast<derived *>(bp);
現在, dr
和dp
指向上面相同的d
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.