[英]dynamic_cast from “void *”
dynamic_cast
僅適用於多態類型,即包含虛函數的類。
在 gcc 中,您可以將dynamic_cast
為void*
但不能從:
struct S
{
virtual ~S() {}
};
int main()
{
S* p = new S();
void* v = dynamic_cast<void*>(p);
S* p1 = dynamic_cast<S*>(v); // gives an error
}
在5.2.7 - Dynamic cast [expr.dynamic.cast]
它說對於dynamic_cast<T>(v)
:
T
是指針類型,則v
應是指向完整類類型的指針的右值T
是引用類型,則v
應該是完整類類型的左值(感謝 usta 評論我的遺漏)...
v
應該是指向多態類型的指針或左值因此,不,不允許使用(void*)
值。
讓我們考慮一下您的請求可能意味着什么:假設您有一個真正指向Derived1*
的指針,但代碼dynamic_cast
-ing 只知道它是一個void*
。 假設您正在嘗試將其Derived2*
轉換為Derived2*
,其中兩個派生類都有一個共同的基礎。 從表面上看,您可能認為所有的指針都指向同一個Base
對象,該對象將包含一個指向相關虛擬調度表和 RTTI 的指針,因此一切都可以掛在一起。 但是,考慮到派生類可能有多個基類,因此所需的Base
類子對象可能不是Derived*
(僅作為void*
可用)所指向的對象。 這行不通。 結論:編譯器需要知道這些類型,以便它可以根據所涉及的類型對指針進行一些調整。
Derived1* -----> [AnotherBase] [[VDT]Base] <-- but, need a pointer to start of [extra members] this sub-object for dynamic_cast
(有些答案談到需要將您從其強制轉換為具有虛函數的多態類型的指針。這都是有效的,但有點誤導。正如您在上面看到的,即使void*
是這樣的如果沒有完整的類型信息,它仍然無法可靠地工作,因為真正的問題是void*
可能指向派生對象的開始,而您需要一個指向基類子對象的指針,從中進行轉換 -鍵入派生。)
確實, void*
不能被dynamically_cast
ed。
你可能記錯了。 使用 g++ 4.5 和以下代碼
struct A {
virtual ~A();
};
int main() {
A a;
void *p = &a;
A* pa = dynamic_cast<A*>(p);
}
我收到以下錯誤:
不能 dynamic_cast 'p'(類型為 'void*')到類型 'struct A*' (源不是指向類的指針)
我猜您將dynamic_cast
與void*
混淆了。 這是合法的,並獲得指向最派生類對象的指針。
來自void*
dynamic_cast
是非法的 - 所轉換的類型必須是多態的 - 至少包含一個虛擬函數(虛擬析構函數也很重要)。
為了補充托尼的好答案,這個小代碼片段出於某種原因對我有幫助。 首先,我們建立一個簡單的層次結構。 然后,我們看看dynamic_cast
可以“生存” static_cast
。 在這個實驗之前,我認為“運行時類型信息在那里,動態轉換應該弄清楚”。 現在我意識到“ dynamic_cast
必須根據編譯器知道的一些表來查找它的信息,所以它不能有什么神奇的力量。”
#include <iostream>
#include <cassert>
using namespace std;
class A {
protected:
virtual void foo() { cout << "A" << endl; }
};
class B1 : public A {
private:
virtual void foo() override { cout << "B1" << endl; }
};
class B2 : public A {
public:
virtual void foo() override { cout << "B2" << endl; }
};
int main(int argc, char **argv) {
B1 b1;
// undefined behavior even though dynamic_cast didn't return null
dynamic_cast<B2*>(
static_cast<B2*>(
static_cast<A*>(&b1)))->foo();
// dynamic_cast returns null here though
assert (!dynamic_cast<B2*>
(static_cast<A*>
(static_cast<B2*>
(static_cast<A*>(&b1)))));
}
您可以將指向多態類型的指針轉換為void *
,但反之則不然。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.