c++ - 在 C++ 中转换为 void* 和 typedef

标签 c++ c casting undefined-behavior void-pointers

我正在通过编写 C 接口(interface)来包装 C++ 库。为此,我创建了一个 C 头文件,其中大多数函数返回/接受 void* 而不是 C++ 类指针。

我知道在 C++ 中从/到 void* 进行转换是危险的,请参阅 Casting to void* and Back to Original_Data_Type*

目前,通过继承,我总是在分配给 void* 之前强制转换为对象的基类

void* temp = static_cast<BaseClass*>(ptr)

返回

BaseClass* base = static_cast<BaseClass*>(voidPtr)
DerivedClass* derived = dynamic_cast<DerivedClass*>(base)

但是,在头文件中使用 void* 会删除语义并使复杂的函数难以阅读。 例如:

void myComplexFunc(void* index, void* data, void* somethingElse)

为了缓解这个问题,我想使用 typedef,即使它们没有提供任何类型安全性,至少它们可以为读者提供一些见解。 将上一个片段与此片段进行比较

extern "C" 
{
...
typedef void Index;
typedef void DBRecord;
typedef void DBResult;
void myComplexFunc(Index* index, DBRecord* data, DBResult* somethingElse)
...
}

基本上,当多个 void* 用作函数的参数时,这些 typedef 充当文档的排序(请记住,我正在包装多个 C++ 类,每个类都有 10 个方法,所以有'很多函数都将 void* 作为第一个参数)。

因此我想使用 typedef

extern "C" // In.h file (declaration)
{
typedef void Index;
...
Index* getIndex();
void modifyIndex(Index* index);
...
// In .cpp file (definition)
Index* getIndex() {
  DerivedCppIndex* derived = ...
  BaseCppIndex* base = static_cast<BaseCppIndex*>(derived)
  return base;
}
...
void modifyIndex(Index* index) {
  BaseCppIndex* base = static_cast<BaseCppIndex*>(index);
  DerivedCppIndex* derived = dynamic_cast<DerivedCppIndex*>(base);
  ...
}

使用 typedef 代替 void* 是否会导致有关 void* 赋值问题的任何问题?

最佳答案

它不会造成任何麻烦,但只会给 API 用户带来错误的安全感(因为任何任意指针都可以工作)。如果您执行以下操作,则没有什么可以阻止编译器提示:

int i;
// ....
modifyIndex(&i);

因此,虽然您不会遇到任何问题,但也不会进行任何编译时检查和强制执行。

请注意,您可以选择简单地声明类而不实际定义它。

解决 void 指针“问题”的正确方法(这并不是一个真正的问题,它只是 C(以及 C++)的一个方面,如果没有适当的方法,可能会使代码难以维护care/documentation)是以某种方式将 Index 公开为不透明类型;例如

// index.h
class Index;
// ...
void modifyIndex(Index *i);

关于c++ - 在 C++ 中转换为 void* 和 typedef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36267339/

相关文章:

c - 将双指针传递给函数

c - 带字符的链表(字符串问题

java - 性能偏执狂 : how much expensive are Float. parseFloat(String), Integer.parseInt(String)?

c++ - 转换运算符如何返回值?

c++ - 定义类的类枚举常量而不提供对类构造函数的访问

c++ - 使用 namespace 行为背后的基本原理

c++ - 此哈希仅适用于枚举类型

c++ - 如何捕获 64 位应用程序上的堆栈损坏?

c - 定义结构的程序局部指针

C# 通过对象拆箱