使用使用 C 风格继承的 C API 时(利用 C 结构的标准布局),例如 GLib ,我们通常使用C风格的强制转换来进行向下转换:
struct base_object
{
int x;
int y;
int z;
};
struct derived_object
{
base_object base;
int foo;
int bar;
};
void func(base_object* b)
{
derived_object* d = (derived_object*) b; /* Downcast */
}
但是,如果我们正在编写使用这样的 C-API 的新 C++ 代码,我们应该继续使用 C 风格的强制转换,还是应该更喜欢 C++ 强制转换?如果是后者,我们应该使用什么类型的 C++ 强制转换来模拟 C 向下强制转换?
起初,我认为reinterpret_cast
会合适:
derived_object* d = reinterpret_cast<derived_object*>(b);
但是,我始终对 reinterpret_cast
保持警惕,因为 C++ 标准 guarantees very little关于将会发生什么。使用 static_cast
到 void*
可能更安全:
derived_object* d = static_cast<derived_object*>(static_cast<void*>(b))
当然,这确实很麻烦,让我觉得在这种情况下最好只使用 C 风格的强制转换。
那么这里的最佳实践是什么?
最佳答案
如果您查看 C++ 规范中的 C 风格强制转换规范,您会发现强制转换表示法是根据其他类型转换运算符(dynamic_cast
、static_cast
、reinterpret_cast
、const_cast
),在本例中使用 reinterpret_cast
。
此外,reinterpret_cast
提供的保证比您链接到的答案所表明的更多。您关心的是:
§ 9.2/20: A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
如果您想使用强制转换表示法,我认为显式使用 C++ 类型转换运算符是最好的。然而,您应该为每个转换编写一个函数(使用reinterpret_cast
实现),然后使用它,而不是在代码中乱扔乱七八糟的强制转换。
derived_object *downcast_to_derived(base_object *b) {
return reinterpret_cast<derived_object*>(b);
}
关于用于 C 风格向下转型的 C++ 转型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15187650/