6

これが私のテスト例です:

struct base {
    virtual ~base(){}
    int x;
};

struct derived: public virtual base {
    base * clone() {
        return new derived;
    }
    derived(): s("a") {}
    std::string s;
};

int main () {
    derived d;
    base * b = d.clone();
    derived * t = reinterpret_cast<derived*>(b);
    std::cout << t->s << std::endl;
    return 0;
}

s を印刷する行でクラッシュします。「b」は派生クラスへのポインターであるため、reinterpret_cast は機能するはずです。なぜクラッシュするのか不思議です。同時に、reinterpret_cast を dynamic_cast に置き換えると、機能します。

4

3 に答える 3

14

動的に型のbがここにある場合でも、を使用する必要があります。これは 、実行時に基本クラスのポインターを派生クラスに動的に変換するためのものです。deriveddynamic_castdynamic_cast

reinterpret_cast生のポインターを取り、それを派生型であると見なします。ただし、virtual継承のため、正しいメソッド ディスパッチ テーブルを指すようにポインターを少し調整する必要がありdynamic_castます。

于 2011-09-13T23:09:52.653 に答える
1

あなたreinterpret_castの場合のように、多重継承または仮想継承で問題が発生します。ここstatic_castで仕事をしませんか?

その理由を知るには、仮想継承の実装を検索してください。一般的な方法は、オブジェクト内の基底クラスへのポインターを格納することです。そのため、仮想基底はその派生クラスと同じアドレスを共有しません。多重継承を使用する場合にも同様のケースがあります。

要するに、reinterpret_castポインターを int にキャストして戻すこと以上のことはできません (int にポインターを格納するのに十分なサイズがある場合)。

于 2011-09-13T23:07:40.080 に答える
0

ここでの他の回答が示唆しているように、へのポインターの値は実際にはへのポインターと異なるreinterpret_castため、この方法では使用できません。有効なポインターは実行時に推定されるため、 を使用する必要があります。設計時に、最も派生したクラス (キャスト先のクラス) がポインターを持つ型から派生した中間型がわからないため、機能しませんbasederiveddynamic_caststatic_cast

ここでの本当の問題は次のとおりです。設計時に、derivedポインターからポインターを計算する方法を知っていbaseます。実行時のペナルティ (の) をどのdynamic_castように回避できますか?

率直に言って、ここには本当に良いオプションはありませんが、考えられるオプションは、次のように、ルート クラス内の定数ポインターに最も派生した型へのポインターを格納することです。

struct base {
  void* const self;
  virtual ~base() {}
  protected:
    base(void* self) : self(self) {}
};
struct derived : public virtual base {
  derived() : base(this) {}
}

これは、パフォーマンスのために型の安全性を犠牲にするため、見苦しく危険です (本当に運が良ければ、わずかなランタイム パフォーマンスが得られます)。ただし、ポインター ( type のメンバー) をポインターにすることができreinterpret_castます。baseselfvoid*derived

于 2011-09-13T23:26:44.153 に答える