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 **'

请有人向我解释为什么不允许第二个例子。请不要引用 C++ 标准作为您的全部答案,因为我已经看到引用它的答案,但我不明白它们的意思。我想了解为什么第二个示例不起作用(即,如果您可以举一个危险的示例,那将是一个很大的帮助)。因为我不明白。对我来说,这两个例子都是投射指针。为什么额外的间接级别会产生任何影响?

4

2 回答 2

12

指针可以void *指向“任何东西”,将所有指针转换为 avoid *是有效的,将所有指针从转换void *为其他类型也是有效的。

但是,avoid **是指向void *值的指针。achar **是一个指向char *值的指针。这些类型并不指向可以相互转换的类型。你可以,如果你需要这样做,使用void **vpp = reinterpret_cast<void **>(cpp);,但它“不安全”(你基本上是在告诉编译器“看,我知道我在这里做什么,所以就去做吧”,这可能不会做你实际上预期的...)

于 2013-04-29T14:15:41.537 回答
6

限制是为了避免破坏类型系统。第一次转换很好:

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

当你放弃类型时,你不能对原始值造成太大的损害,因为对一个void对象几乎没有什么可做的,所有对指针的更改vp都是本地的,不会影响p.

如果允许第二种情况:

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!!!

类型系统已被颠覆。

也就是说,问题在于,在第二种情况下,存在可以应用于目标指针的操作,这些操作可以修改原始对象并导致错误。const在其他情况下可以找到类似的示例(您可以转换int*const int*,但不能转换int**const int**...)。

于 2013-04-29T14:31:13.203 回答