this によると、void*
にはRTTI情報がないため、void*
からのキャストは不正であり、意味があります。
私の記憶が正しければ、dynamic_cast
のvoid*
がgccで作業していた。
問題を明確にしていただけませんか。
dynamic_cast
は、ポリモーフィック型、つまり仮想関数を含むクラスでのみ機能します。
Gccではdynamic_cast
tovoid*
ではなくfrom:
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
は完全なクラス型の左辺値になります(欠落しているthisについてコメントしてくれたustaに感謝)...
v
は多相型へのポインタまたは左辺値になりますしたがって、いいえ、_(void*)
_ valueは使用できません。
あなたのリクエストが何を意味するのか考えてみましょう:_Derived1*
_へのポインターを持っているとしますが、コード_dynamic_cast
_- ingはそれが_void*
_であることだけを知っています。それを_Derived2*
_にキャストしようとしているとしましょう。ここで、両方の派生クラスは共通のベースを持っています。表面的には、すべてのポインタが関連する仮想ディスパッチテーブルとRTTIへのポインタを含む同じBase
オブジェクトを指していると考えるかもしれません。ただし、派生クラスには複数の基本クラスが含まれる可能性があるため、必要な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);
}
次のエラーが発生します。
dynamic_cast 'p'(タイプ 'void *')からタイプ 'struct A *'にできません(ソースはクラスへのポインターではありません)
dynamic_cast
tovoid*
と混同していると思います。これは正当であり、最も派生したクラスオブジェクトへのポインタを取得します。
dynamic_cast
fromvoid*
は不正です-キャスト元の型はポリモーフィックでなければなりません-少なくとも1つの仮想関数が含まれています(仮想デストラクタもカウントされます)。
トニーのニースの答えに追加するために、この小さなコードスニペットは、何らかの理由で私に役立ちます。まず、単純な階層を確立します。次に、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 *
にキャストできますが、その逆はできません。