用于 C 风格向下转型的 C++ 转型

标签 c++ c

使用使用 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_castvoid* 可能更安全:

derived_object* d = static_cast<derived_object*>(static_cast<void*>(b))

当然,这确实很麻烦,让我觉得在这种情况下最好只使用 C 风格的强制转换。

那么这里的最佳实践是什么?

最佳答案

如果您查看 C++ 规范中的 C 风格强制转换规范,您会发现强制转换表示法是根据其他类型转换运算符(dynamic_caststatic_castreinterpret_castconst_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/

相关文章:

是否可以静态定义 std in/out/err 以外的文件描述符?

c - 指向函数指针数组的指针

c - C代码输出说明

c - 通过递归函数打印链表的节点

c++ - 如何从 C++ 返回 char ** 并使用 ctypes 将其填充到 Python 列表中?

c++ - sqlite 数据库保持锁定/不可访问

C++ 使用 int 从列表中设置枚举

c++ - 控制台 RPG 游戏 - 攻击和健康功能 - C++

C++ lambda/回调弹出窗口?

c - 为什么未初始化的局部变量总是具有相同的初始值?