【发布时间】:2011-06-24 16:50:19
【问题描述】:
假设我有一个实现多个接口的类
class CMyClass : public IInterface1, public IInterface2 { };
在该类的成员函数中,我需要获得指向其中一个接口的void* 指针(IUnknown::QueryInterface() 中的典型情况。
典型的解决方案是使用static_cast来实现指针调整:
void* pointer = static_cast<IInterface2*>( this );
如果没有从CMyClass 继承的已知类,在这种情况下是安全的。但是如果存在这样的类:
class CDerivedClass : public CUnrelatedClass, public CMyClass {};
我不小心做了
void* pointer = static_cast<CDerivedClass*>( this );
而this 实际上是一个指向CMyClass 实例的指针,编译器不会捕捉到我,并且程序稍后可能会遇到未定义的行为——static_cast 变得不安全。
建议的解决方案是使用隐式转换:
IInterface2* interfacePointer = this;
void* pointer = interfacePointer;
看起来这将解决两个问题 - 指针调整和无效向下转换的风险。
第二种方案有什么问题吗?喜欢第一个的原因可能是什么?
【问题讨论】:
-
有趣的是
CMyClass在这里知道CDerivedClass...不是不可能,甚至不是糟糕设计的真正迹象,但在一般情况下,CMyClass不应该有任何知识的后代。我可以想象在头文件和定义CMyClass方法的翻译单元中定义这两个类,包括两者,在VS中更是如此,因为它倾向于提倡预编译的头文件......仍然值得深思。