c++类型转换,用于C风格的向下转换
C++ casting for C-style downcasting
当使用使用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++代码,使用像这样的C- api,我们应该继续使用C风格的强制转换,还是应该使用c++强制转换?如果是后者,我们应该使用哪种类型的c++强制转换来模拟C向下强制转换?
起初,我认为reinterpret_cast
是合适的:
derived_object* d = reinterpret_cast<derived_object*>(b);
然而,我总是对reinterpret_cast
保持警惕,因为c++标准对将要发生的事情几乎没有保证。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:使用reinterpret_cast适当转换后,指向标准布局结构对象的指针指向其初始成员(或者,如果该成员是位域,则指向其所在的单元),反之亦然。
如果你想使用强制转换表示法,我认为明确使用c++类型转换操作符是最好的。但是,与其在代码中乱扔强制类型转换,不如为每个转换编写一个函数(使用reinterpret_cast
实现),然后使用它。
derived_object *downcast_to_derived(base_object *b) {
return reinterpret_cast<derived_object*>(b);
}
然而,我总是对reinterpret_cast保持警惕,因为c++标准对将要发生的事情几乎没有保证。
c++风格的强制转换并不比C风格的强制转换更安全,因为C风格的强制转换是根据c++风格的强制转换定义的。
5.4.4 执行的转换- a const_cast (5.2.11),
-一个static_cast (5.2.9),
—一个static_cast后跟一个const_cast,
-一个reinterpret_cast(5.2.10),或
—reinterpret_cast后跟const_cast,
可以使用显式类型转换的强制转换符号来执行。
[…]
如果一个转换可以用以上列出的一种以上的方式来解释,那么这种解释出现在列表的第一个被使用,即使由该解释产生的强制转换是错误的。
可悲的答案是,你无法避免代码中的强制类型转换,因为编译器对类之间的关系知之甚少。无论如何,您可能想要重构它(强制类型转换、类或使用它们的代码)。
底线是:
如果可以,使用适当的继承。
如果不能,使用reinterpret_cast
使用如下C- api的新c++代码
不要用C风格编写新的c++代码,它不能利用c++语言的特性,而且它还迫使包装器的用户使用相同的"C"风格。相反,创建一个合适的c++类来包装C API接口细节,并将它们隐藏在c++类后面。
没有应该继续使用c风格的强制类型转换吗
或者我们应该使用c++强制类型转换
是的,但只有当你必须的时候。
使用c++继承和虚访问器函数(可能)。请说明你打算如何在函数中使用派生对象,这可能会为你提供一个更好的答案。
如果func期望使用派生对象的方法,那么它应该接收派生对象。如果它期望使用base_object的方法,但由于指针指向派生对象而改变了方法,则虚函数是实现此目的的c++方法。
同时,你想传递一个引用给func,而不是一个指针。
dynamic_cast,需要满足某些条件:
http://www.cplusplus.com/doc/tutorial/typecasting/如果你只是转换结构体ptrs到结构体ptrs,你知道你想要什么,那么static_cast,或reinterpret_cast可能是最好的?
但是,如果您真的对编写c++代码感兴趣,那么强制类型转换应该是您最后的手段,因为有更好的模式。我考虑强制转换的两种常见情况是:
您正在与一些事件传递机制接口,该机制将泛型基类传递给事件处理程序。
你有一个对象的容器。容器要求它包含同质类型(即每个元素都包含相同的"东西"),但你想在容器中存储不同的类型。
我认为dynamic_cast
正是你想要的。
- cv::Mat灰色风格转换
- 将 GCC/ATT 风格的汇编器转换为可视化工作室汇编器
- 在没有c风格强制转换的情况下,将DWORD_PTR强制转换为class,反之亦然
- 我应该使用c++的reinterpret_cast而不是C风格的强制转换吗?
- 使用c++风格的类型转换将int转换为char
- c++中的构造函数调用或函数风格强制转换
- 将任何容器转换为c风格的数组视图
- Reinterpret_cast与c风格的强制转换
- 旧风格使用sys/select.h宏强制转换警告
- c++枚举类型可以作为函数调用吗?或者它只是一种不同风格的类型转换
- 将字符串转换为c风格字符串并检测空终止字符
- 难以理解c风格的类型转换和动态转换
- c++中的C风格强制转换会产生奇怪的行为
- 在哪些情况下,基类到派生类的c风格强制转换可能导致崩溃
- 通过c风格转换将char*转换为QString
- c++规范是否说明如何在static_cast/const_cast链中选择用于C风格强制转换的类型?
- 转换需要reinterpret_cast、c风格强制转换或函数风格强制转换
- 将c风格的程序转换为c++
- c++类型转换,用于C风格的向下转换
- 编译器开关在c风格的强制转换中禁用const_cast语义