'type-casting abstract class type to struct type with a integer member
I am studing Blender's GHOST code and found the following statement in GHOST_CreateSystem C-API function
GHOST_ISystem::createSystem();
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return (GHOST_SystemHandle)system;
GHOST_ISystem is an abstract class for a specific operating system such as win32, linux.
GHOST_SystemHandle is defined as structure type as follows:
typedef struct GHOST_SystemHandle__ {
int unused;
} * GHOST_SystemHandle
I am not familiar with this kind of practice type-casting a pointer to class into a pointer to struct type with an integer member.
It would be appreciated to enlighten me the background about it.
Solution 1:[1]
Abstract class CANNOT be instantiated, to wit it cannot be converted. What happens here is a conversion of pointer values.
The calls GHOST_ISystem::createSystem(); and GHOST_ISystem::getSystem(); are calls to static functions. The latter returns a pointer to GHOST_ISystem. Pointer is a separate compound type and pointer to any declared type may materialized. A pointer to an abstract class-type can hold value of pointer to any derived type. GHOST_ISystem* is its static type while its dynamic type can vary.
The C-style cast syntax (GHOST_SystemHandle)system; is considered faux pas in C++ as it is too permitting, unsafe conversion. In this particular case it is treated as reinterpret_cast to a pointer GHOST_SystemHandle__ *.
The content of pointer system is bytewise copied to an instance of GHOST_SystemHandle, which is also a pointer. This would be hinged on assumption that all pointers in implementation have similar content and same size and that access by dereferencing the result would be legal.
Likely, the underlying reason was that derived types would have an integer field or an subobject with same alignment. Strictly speaking, result is unspecified. Memory model of original class and GHOST_SystemHandle__ should match. This assumes too many things:
- The abstract base class-type have no non-static member variable or it contains an equivalent member variable.
- The implementation is conforming to late-enough standard to ensure that base type subobject got zero size, if it doesn't have non-static member variables.
- The alignment requirement of
derived type in question is same as alignment requirement of
GHOST_SystemHandle__. It it's not, result of*system->unusedis undefined.
There is a number of ways it could be avoided in C++ and none was used, which suggests that code was converted from C without much of refactoring done while keeping interface type formats same for compatibility.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
