8

void*以下の例のように、派生クラスのメンバーへのポインターを、そこから基本クラスのポインターにキャストしたいと思います。

#include <iostream>

class Base
{
    public:
       void function1(){std::cout<<"1"<<std::endl;}
       virtual void function2()=0;
};

class Derived : public Base
{
    public:
       virtual void function2(){std::cout<<"2"<<std::endl;}
};

int main()
{
    Derived d;
    void ptr* = static_cast<void*>(&d);
    Base* baseptr=static_cast<Base*>(ptr);
    baseptr->function1();
    baseptr->function2(); 
}

これはコンパイルされ、目的の結果 (出力12それぞれ) が得られますが、動作することが保証されていますか? static_castここで見つけたの説明: http://en.cppreference.com/w/cpp/language/static_castは、同じvoid*クラスへのポインターへの変換とそのポインターへの 変換についてのみ言及しています(ポイント10)。

4

3 に答える 3

8

一般的なケースでは、静的キャストを介してベースを void から派生 (またはその逆) に変換することは安全ではありません。

ほぼ確実に機能する場合があります。関連するすべてがポッドまたは標準レイアウトであり、単一の継承のみが関与している場合、少なくとも実際には問題はないはずです。標準の章と節はありません、しかし一般的な考え方は、その場合のベースは派生物のプレフィックスであることが保証されており、それらはアドレスを共有するということです.

これが失敗することを確認したい場合は、virtual継承、多重継承 (両方virtualとそうでないもの)、および自明ではない多重実装継承を混ぜてください。基本的に、異なるタイプのビューのアドレスが異なる場合、異なるタイプへthisvoidキャストとその逆のキャストは運命づけられています。私は実際にこれが失敗するのを見てきました.(キャストのポイントから遠く離れたコードベースの変更により)失敗する可能性があるという事実が、まったく同じ型のvoidポインターとの間で常にキャストすることに注意する必要がある理由です. .

于 2013-10-27T03:55:56.533 に答える
0

自分で提供したリンクから

9) 一部のクラス D のメンバーへのポインターは、その基本クラス B のメンバーへのポインターにアップキャストできます。

つまり、アップキャストを行う前に安全であることを知っている限り、動作が保証されます。そのため、失敗した場合 dynamic_castは which を使用する必要があります。nullptr

ある場合は、このように考えてください。

Type * t1;

static_castt1 から派生するクラスの 1 つへの変更は、プログラムを詳細に分析しない限り、コンパイル時に知ることはできません (これは明らかにそうではなく、行うべきではありません)。チェック中。dynamic_cast変換が成功したかどうかを確認するために実行時に余分な作業を行うため、接頭辞は動的です。

于 2013-10-27T03:36:25.293 に答える