これによると、void*
はRTTI情報を持っていないため、からのキャストvoid*
は合法ではなく、意味があります。
私が正しく覚えていれば、dynamic_cast
fromvoid*
はgccに取り組んでいました。
問題を明確にしていただけませんか。
これによると、void*
はRTTI情報を持っていないため、からのキャストvoid*
は合法ではなく、意味があります。
私が正しく覚えていれば、dynamic_cast
fromvoid*
はgccに取り組んでいました。
問題を明確にしていただけませんか。
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*
両方の派生クラスが共通のベースを持つにキャストしようとしているとしましょう。表面的には、すべてのポインターが同じオブジェクトを指していると思うかもしれません。このBase
オブジェクトには、関連する仮想ディスパッチテーブルとRTTIへのポインターが含まれているため、すべてが一緒にハングする可能性があります。ただし、派生クラスには複数の基本クラスがある可能性があるため、必要なBase
クラスサブオブジェクトは、Derived*
-としてのみ使用可能なものではない可能性があることを考慮してください。void*
-指しています。それはうまくいきません。結論:コンパイラーはこれらのタイプを認識している必要があります。これにより、関連するタイプに基づいてポインターを調整できます。
Derived1 * -----> [AnotherBase] [[VDT] Base] <-ただし、開始するにはポインタが必要です [追加メンバー]dynamic_castのこのサブオブジェクト
(いくつかの回答は、キャスト元のポインターが仮想関数を持つポリモーフィックタイプである必要があることについて述べています。これはすべて有効ですが、少し誤解を招きます。上記のように、そのようなタイプのポインターであってもvoid*
、完全な型情報がないと、まだ確実に機能しません。実際の問題は、void*
おそらく派生オブジェクトの先頭を指していることですが、キャスト先型の派生元である基本クラスのサブオブジェクトへのポインターが必要です。 )。
から編集void*
できないのは事実です。dynamically_cast
あなたはおそらく覚えていません。g++4.5と次のコードを使用
struct A {
virtual ~A();
};
int main() {
A a;
void *p = &a;
A* pa = dynamic_cast<A*>(p);
}
次のエラーが発生します。
'p'(タイプ'void *')をタイプ'struct A *'に動的にキャストすることはできません(ソースはクラスへのポインターではありません)
私はあなたがと混同しdynamic_cast
て void*
いると思います。これは合法であり、最も派生したクラスオブジェクトへのポインタを取得します。
dynamic_cast
from void*
は不正です-キャスト元の型はポリモーフィックである必要があります-少なくとも1つの仮想関数が含まれています(仮想デストラクタもカウントされます)。
Tonyの良い答えに追加するために、この小さなコードスニペットは何らかの理由で私を助けてくれます。まず、単純な階層を確立します。次に、を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 *
、その逆はできません。