7

私が次のことをすれば、すべて問題ありません:

char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok

しかし、以下はそうではありません:

char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
                               //cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
                               //cannot convert from 'void **' to 'char **'

2番目の例が許可されていない理由を誰か説明してください。C++ 標準を回答全体として引用しないでください。それを引用する回答を既に見たことがありますが、その意味がわかりません。2 番目の例が機能しない理由を理解したいと思います (つまり、危険な例を挙げていただければ大変助かります)。わからないから。私にとって、どちらの例もポインターのキャストです。追加レベルの間接化によって違いが生じるのはなぜですか?

4

2 に答える 2

12

void *ポインターは「何でも」を指すことができ、すべてのポインターを に変換することは有効であり、すべてのポインターを から他の型void *に変換することも有効です。void *

ただし、avoid **は値を指すポインタvoid *です。achar **は値を指すポインターchar *です。これらの型は、相互に変換可能な型を指していません。これを行う必要がある場合は、を使用できますが、void **vpp = reinterpret_cast<void **>(cpp);それは「安全ではありません」(基本的に、コンパイラに「見て、ここで何をしているのかわかっているので、それを実行してください」と伝えているため、実際には実行されない可能性があります)。期待される...)

于 2013-04-29T14:15:41.537 に答える
6

制限は、型システムを壊さないようにすることです。最初の変換は問題ありません:

type *p = ...;
void *vp = p;

型を譲渡している間は、オブジェクトで行うことがほとんどなく、すべての変更はポインターに対してローカルであり、に影響を与えることができないためvoidvp元の値に大きなダメージを与えることはできませんp

2 番目のケースが許可された場合:

type **p = ...;
void **vp = p;

次に、見た目が完璧で正しいコードがアプリケーションを壊す可能性があります。例えば:

int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double();  // now parray[0] is a pointer to a double object, 
                     // not a pointer to an int!!!

型システムが覆されました。

つまり、問題は、2 番目のケースでは、元のオブジェクトを変更してバグを引き起こす可能性のある宛先ポインターに適用できる操作があることです。const他のケースでも同様の例が見られます ( に変換できますが、 ... に変換int*するconst int*ことはできません)。int**const int**

于 2013-04-29T14:31:13.203 に答える