在 C++ 中转换为 void* 和 typedef
Casting to void* and typedefs in C++
我正在通过编写 C 接口来包装 C++ 库。出于这个原因,我创建了一个 C 头文件,其中大多数函数 return/accept void*
而不是 C++ class 指针。
我知道在 C++ 中转换 from/to void* 是危险的,请参阅
Casting to void* and Back to Original_Data_Type*
目前通过继承,我总是在分配给 void*
之前强制转换为对象的基 class
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,即使它们不提供任何类型安全性,但至少它们会给 reader 一些见解。
将上一个片段与这个片段进行比较
extern "C"
{
...
typedef void Index;
typedef void DBRecord;
typedef void DBResult;
void myComplexFunc(Index* index, DBRecord* data, DBResult* somethingElse)
...
}
基本上,当多个 void*
被用作函数的参数时,这些 typedef 充当文档的一种(请记住,我正在包装多个 C++ classes,每个都有 10 个方法,所以有很多函数将 void* 作为第一个参数。
出于这个原因,我想使用 typedefs
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);
因此,虽然您不会遇到任何问题,但您也不会有任何编译时检查和强制执行。
请注意,您可以选择简单地声明 class 而无需实际定义它。
解决 void-pointer "problem" 的正确方法(这并不是一个真正的 问题,它只是 C(以及 C++)的一个方面,它可能使代码在没有适当 care/documentation 的情况下难以维护)是以某种方式将 Index
公开为不透明类型;例如
// index.h
class Index;
// ...
void modifyIndex(Index *i);
为 void
创建一个 typedef 有点笨拙。更常见的做法是将 void*
定义为 IndexHandle
并强制代码的客户端读取或传递不透明句柄类型的值作为参数。所有转换都应在您的代码中进行。
我正在通过编写 C 接口来包装 C++ 库。出于这个原因,我创建了一个 C 头文件,其中大多数函数 return/accept void*
而不是 C++ class 指针。
我知道在 C++ 中转换 from/to void* 是危险的,请参阅 Casting to void* and Back to Original_Data_Type*
目前通过继承,我总是在分配给 void*
之前强制转换为对象的基 classvoid* 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,即使它们不提供任何类型安全性,但至少它们会给 reader 一些见解。 将上一个片段与这个片段进行比较
extern "C"
{
...
typedef void Index;
typedef void DBRecord;
typedef void DBResult;
void myComplexFunc(Index* index, DBRecord* data, DBResult* somethingElse)
...
}
基本上,当多个 void*
被用作函数的参数时,这些 typedef 充当文档的一种(请记住,我正在包装多个 C++ classes,每个都有 10 个方法,所以有很多函数将 void* 作为第一个参数。
出于这个原因,我想使用 typedefs
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);
因此,虽然您不会遇到任何问题,但您也不会有任何编译时检查和强制执行。
请注意,您可以选择简单地声明 class 而无需实际定义它。
解决 void-pointer "problem" 的正确方法(这并不是一个真正的 问题,它只是 C(以及 C++)的一个方面,它可能使代码在没有适当 care/documentation 的情况下难以维护)是以某种方式将 Index
公开为不透明类型;例如
// index.h
class Index;
// ...
void modifyIndex(Index *i);
为 void
创建一个 typedef 有点笨拙。更常见的做法是将 void*
定义为 IndexHandle
并强制代码的客户端读取或传递不透明句柄类型的值作为参数。所有转换都应在您的代码中进行。