在阅读Qt源代码时,我遇到了这个宝石:
template <class T> inline T qgraphicsitem_cast(const QGraphicsItem *item) { return int(static_cast<T>(0)->Type) == int(QGraphicsItem::Type) || (item && int(static_cast<T>(0)->Type) == item->type()) ? static_cast<T>(item) : 0; }
注意static_cast< T>(0) – > Type?我一直在使用C多年,但从未见过0在static_cast之前使用.这段代码是做什么的,它是安全的吗?
背景:如果从QGraphicsItem派生,您将声明一个名为Type的唯一枚举值,并实现一个名为type的虚拟函数,返回它,例如:
class Item : public QGraphicsItem { public: enum { Type = MAGIC_NUMBER }; int type() const { return Type; } ... };
你可以这样做:
QGraphicsItem* item = new Item; ... Item* derivedItem = qgraphicsitem_cast<Item*>(item);
这可能有助于解释static_cast正在尝试做什么.
解决方法
这看起来像一个非常可疑的方式来静态地声明模板参数T有一个类型成员,然后验证其值是预期的魔术数字,就像你说的那样你应该做的.
因为Type是一个枚举值,所以不需要这个指针来访问它,所以static_cast< Item>(0) – > Type检索Item :: Type的值,而不实际使用指针的值.所以这有效,但是可能是未定义的行为(取决于您对标准的看法,但是IMO是一个坏主意),因为代码使用指针dereference操作符( – >)来引用NULL指针.但是,我不能想像为什么这更好的只是Item :: Type或模板T :: Type – 也许这是旧的代码设计工作在旧的编译器与不良的模板支持,无法解决什么T :: Type应该是意思
尽管如此,最终的结果是在编译时由于bool没有类型成员枚举而导致的代码如qgraphicsitem_cast< bool>(ptr)将失败.这比运行时检查更可靠和便宜,即使代码看起来像一个黑客.