简体   繁体   中英

Casting to void* and typedefs in C++

I'm wrapping a C++ library by writing a C interface. For this reason i created a C header file where most of the functions return/accept void* instead of C++ class pointers.

I know that is dangerous to cast from/to void* in C++, see Casting to void* and Back to Original_Data_Type*

Currently with inheritance i'm always casting to the base class of an object before assigning to void*

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

and back

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

However using void* in a header files remove semantics and make complex functions hard to read. For example:

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

For mitigating this i wanted to use typedefs that even if they don't give any type safety at least they give to reader some insights. Compare the previous snippet with this one

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

Basically these typedefs act as a sort for documentation when multiple void* are used as parameters of a function (Keep in mind that i'm wrapping multiple C++ classes each with 10 methods, so there're lots of functions that thake a void* as first parameter).

For this reason i wanted to use to 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);
  ...
}

Does the use of a typedef instead of void* causes any trouble regarding the issues of assignment to void*?

It shouldn't cause any trouble, but it will only give API users a false sense of security (as any arbitrary pointer will also work). There's nothing to prevent the compiler from complaining if you do something like:

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

So while you won't have any problems, you won't have any compile-time checks and enforcements either.

Do note that you have the choice of simply declaring the class without actually defining it.

The proper way to solve the void-pointer "problem" (and it's not really a problem , it's just an aspect of C (and thus C++) which may make code difficult to maintain without proper care/documentation) is to somehow expose Index as an opaque type; eg

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

Creating a typedef for void is a bit awkward. More common practice is to define void* as IndexHandle and force clients of your code to read or pass as a parameter a value of the opaque handle type. All casting should take place inside of your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM