7

コールバック関数のコードを記述する必要があります (ATL 内から呼び出されますが、それはそれほど重要ではありません)。

HRESULT callback( void* myObjectVoid )
{
    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    return myObject->CallMethod();
}

ここで、void*は へのポインタであることが保証されているCMyClassため、static_cast合法です。私の懸念は、コードが (少なくとも新しいバージョンの Visual C++ に対して) 可能な限り移植可能でなければならないということです。だから超偏執的になるために、私はCMyClass*ポインタもチェックする傾向があります - つまり、それがnullであることが判明した場合はどうなりますか?

    if( myObjectVoid == 0 ) {
       return E_POINTER;
    }
    CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
    if( myObject == 0 ) {
       return E_POINTER;
    }

2番目のチェックは合理的ですか?static_castnull 以外のポインターを null ポインターに変えることは可能ですか?

4

4 に答える 4

7

static_cast は、異なるオフセットのオブジェクト パーツ間でキャストする場合、ポインター値を変更できます。

class A{ int x; }; class B{ int y; };
class C : A,B {};

C *c=new C(); 

B *b=c; 
// The B part comes after the A part in C. Pointer adjusted

C *c2=static_cast<C*>(b); 
// Pointer gets adjusted back, points to the beginning of the C part

ただし、「ヌル ポインター値 (4.10) は、変換先の型のヌル ポインター値に変換されます。」(5.2.9-8)、つまりがの場合 、も(調整されず) に設定されます。全体が意味することは、NULL 以外の静的キャストがを生成する場合、 の値は何らかの形で型システムを回避することによって取得されたことを意味します。そして、それは、「とにかく起こり得ない」という理由で、コンパイラが 2 番目のチェックを破棄する可能性があることを意味します。cNULLbNULLc2NULLmyObjectVoidNULLmyObjectVoid

于 2010-08-12T15:28:53.120 に答える
6

いいえ。ポインターが有効なオブジェクトを参照し、変換が有効な場合、結果も有効なオブジェクトを参照するため、null にはなりません。どちらかが無効な場合、コードは正しくなく、結果は未定義です。したがって、有効な使用法で null の結果を返す唯一の方法は、null で開始することです。

オブジェクト ポインターと void ポインターの間の変換の特定のケースでは、標準には次のように記載されています (5.2.9/10)。

「オブジェクトへのポインター」型の値を「ポインターへのポインター」に変換しvoid、元のポインター型に戻すと、元の値になります。

そしてこれ (4.10/3)

「T へのポインター」を「T へのポインター」に変換した結果はvoid、型 T のオブジェクトが存在する格納場所の先頭を指します。

したがって、元のオブジェクト ポインターと最終的なオブジェクト ポインターは同じになり、オブジェクト ポインターが同じであるvoid場合に限り、ポインターは null になります。

于 2010-08-12T15:20:50.917 に答える
0

static_castポインタに加える必要がある唯一の変更は、ワード アラインメントです。したがって、理論的にはmyObjectVoid、メモリ内の最後のバイトを指すと、それが 0 に「整列」される可能性がありますが、それは現実的な問題ではないと思います。

于 2010-08-12T14:55:31.257 に答える
0

いいえ、2 番目のチェックは合理的ではありません。static_cast非 null ポインターを null ポインターに変換することはできません。static_castあなたの場合に提供された値(ポインターである)について変更される可能性がある唯一のことは、アドレスを調整することです。それ以外の場合は、式の結果をターゲットの型として扱う必要があることをコンパイラの型分析の残りの部分にアドバイスすることに厳密に関係しています。ポインターの場合、逆参照によってターゲット オブジェクト内の正しいアドレスが検出され、インクリメントとデクリメントのストライドが型のサイズに適していることを意味します。

于 2010-08-12T15:33:35.657 に答える