我需要为回调函数编写代码(它将在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*
指针 - 我的意思是如果它被证明是空的?
if( myObjectVoid == 0 ) {
return E_POINTER;
}
CMyClass* myObject = static_cast<CMyClass*>( myObjectVoid );
if( myObject == 0 ) {
return E_POINTER;
}
第二次检查是否合理? static_cast
是否可以将非空指针转换为空指针?
答案 0 :(得分: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),即如果 c
是NULL
,那么b
也是NULL
(并且未调整) )因此c2
设置为NULL
。整个过程意味着:如果静态转换非NULL myObjectVoid
会产生NULL
,那么myObjectVoid
的值是通过某种方式绕过类型系统获得的。这意味着,编译器可能会抛弃你的第二张支票,因为“它无论如何都不会发生”。
答案 1 :(得分:6)
没有。如果指针引用了有效对象,并且转换有效,则结果也将引用有效对象,因此它不会为null。如果其中一个无效,则代码不正确,结果未定义。因此,有效使用以获得null结果的唯一方法是从null开始。
在对象指针和void指针之间进行转换的特定情况下,标准就是这样说的(5.2.9 / 10):
“指向对象的指针”类型的值转换为“指向
void
的指针”并返回原始指针类型将具有其原始值。
和这(4.10 / 3)
将“指向T的指针”转换为“指向
void
的指针”的结果指向T类型的对象所在的存储位置的起点
所以原始和最终的对象指针将是相同的,当且仅当对象指针是。{/ p>时,void
指针将为null。
答案 2 :(得分:0)
指针的唯一变化是static_cast
用于字对齐。因此,从理论上讲,myObjectVoid
指向内存中的最后一个字节,它可能与0“对齐”,但我不认为这是一个现实的问题。
答案 3 :(得分:0)
不,第二次检查不合理。 static_cast
无法将非空指针转换为空指针。关于您提供的值(作为指针),static_cast
唯一可能改变的是调整地址。否则,它严格关注建议编译器的其余类型分析,表达式的结果应该被视为目标类型。对于指针,这意味着解除引用会在目标对象中找到正确的地址,并且增量和减量步幅适合于类型的大小。