41

これによると、void*はRTTI情報を持っていないため、からのキャストvoid*は合法ではなく、意味があります。

私が正しく覚えていれば、dynamic_castfromvoid*はgccに取り組んでいました。

問題を明確にしていただけませんか。

4

6 に答える 6

48

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
}
于 2010-11-09T06:39:30.053 に答える
21

その中で: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*おそらく派生オブジェクトの先頭を指していることですが、キャスト先型の派生元である基本クラスのサブオブジェクトへのポインターが必要です。 )。

于 2010-11-09T06:46:31.213 に答える
4

から編集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 *'に動的にキャストすることはできません(ソースはクラスへのポインターではありません)

于 2010-11-09T06:39:14.327 に答える
2

私はあなたがと混同しdynamic_cast void*いると思います。これは合法であり、最も派生したクラスオブジェクトへのポインタを取得します。

dynamic_cast from void*は不正です-キャスト元の型はポリモーフィックである必要があります-少なくとも1つの仮想関数が含まれています(仮想デストラクタもカウントされます)。

于 2010-11-09T06:40:49.257 に答える
2

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)))));
}
于 2020-02-25T17:43:19.900 に答える
0

ポリモーフィック型へのポインタをにキャストすることはできますがvoid *、その逆はできません。

于 2010-11-09T06:42:16.360 に答える