I'm writing a C wrapper API for my lib.
I generally pass my C++ objects as void* in C. And there are naturally access wrapper function for every object's public function. The C code does not access native C++ class members.
Yesterday, someone mentioned on IRC that I should not pass around pointer to C++ template classes as void* in C because it's dangerous. Is this true? How different are pointers to ordinary C++ classes from pointers to template classes?
Thanks!
It's bogus. Templates have no special properties re casting that a normal class wouldn't have. Make sure you always use the appropriate cast and you will be fine.
This is unrelated to templates vs. normal classes, but if your class has multiple inheritance you should always start with the same type before casting to void*, and likewise when casting back. The address of a pointer will change based on which parent class the pointer type is.
class ParentA
{
// ...
int datumA;
};
class ParentB
{
// ...
int datumB;
};
class Derived : public ParentA, public ParentB
{
// ...
};
int main()
{
Derived d;
ParentA * ptrA = &d;
ParentB * ptrB = &d;
assert((void*)ptrA == (void*)ptrB); // asserts!
}
It is always safe to cast some pointer Foo* onto void* and then restore on the same type Foo*. When inheritance is used however, a special care should be taken. Upcasting/downcasting shouldn't be done through the void* pointer. Consider the following code:
#include <cassert>
class Parent
{
int bar;
};
class Derived : public Parent
{
virtual void foo() { }
};
int main()
{
Derived d;
Derived* ptr_derived = &d;
void *ptr_derived_void = ptr_derived;
Derived* ptr_derived_from_void = (Derived*)ptr_derived_void;
assert(ptr_derived_from_void == ptr_derived); //that's OK
Parent* ptr_parent = ptr_derived; //upcast
Parent* ptr_parent_from_void = (Parent*)ptr_derived_void; //upcast?
assert(ptr_parent_from_void == ptr_parent); //that's not OK
return 0;
}
Also this post shows some problem with casting through void*.
A template class instantiated with a classes A and B as template args involves the compiler creating two seperate classes that specifically handle these respective types. In many ways this is like an intelligent strongly typed preprocessor macro. It is not that different to manually copy-pasting two seperate "normal" classes who operate on A and B respectively. So no.
The only way it will be dangerous is if you try to cast what was originally:
MyClass<A>
as
MyClass<B>
if A is not B, since they could have a different memory layout.
Pointers are just that: pointers to data. The "type" of a pointer makes no difference to anything really (at compile time), it's just for readability and maintainability of code.
For example:
Foo<a> *x = new Foo<a>();
void *y = (void*)x;
Foo<a> *z = (Foo<a>*)y;
Is perfectly valid and will cause no issues. The only problem when casting pointer types is that you may run into dereferencing issues when you've forgotten what the underlying data-type a pointer is referencing actually is.
If you're passing around void* everywhere, just be careful to maintain type integrity.
Don't do something like:
Foo<a> *x = new Foo<a>();
void *z = (void*)x;
//pass around z for a while, then mistakenly...
Foo<b> *y = (Foo<b>*)z;
By accident!
Related
My C++ is a bit rusty and I don't remember everything in the standard.
I have a void*. In one specific function it is either a class that inherits Alpha or one that inherits Beta. Both base classes have virtual functions. However I can't seem to tell which is which
class Alpha {
public:
virtual void Speak() { printf("A"); }
};
class Beta {
public:
virtual void Speak() { printf("B"); }
};
int main(){
//BAD CODE WILL PRINT TWICE
void *p = new Alpha;
Alpha*a = dynamic_cast<Alpha*>((Alpha*)p);
Beta*b = dynamic_cast<Beta*>((Beta*)p);
if(a)
a->Speak();
if(b)
b->Speak();
return 0;
}
How do I figure out which class is which? There are 100's of classes in this codebase that gets converted to void. Most of them inherit 5 base classes however I'm not eager to find out. Is the only solution inheriting from something like class Dummy {public: virtual void NoOp(){}}; and cast to Dummy before using dynamic cast? Is this safe? I'm hoping there's a better solution but I can't think of anything else.
The only thing you can do with a void* pointer is to cast it back to exactly the same type as the pointer that was cast to void* in the first place. The behaviour on doing anything else is undefined.
What you could do in your case is define
class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};
and make this the base class for Alpha and Beta. Then pass a Base* pointer around rather than a void* one, and take your dynamic_casts directly on p.
Note further that if you declared virtual void Speak() = 0; in Base, then your code in main would become simply
int main(){
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}
As a rule of thumb, casts of any kind are undesirable.
The expression Alpha*a = dynamic_cast<Alpha*>((Alpha*)p); first casts p to Alpha* with an explicit c style cast. Then, that resulting Alpha* is passed through dynamic_cast<Alpha*>. Using dynamic_cast<T*> on a T* pointer (a pointer of the same type as you are trying to cast to) will always provide the input pointer. It cannot be used to confirm that the pointer is valid. From cppreference for dynamic_cast<new_type>(expression) :
If the type of expression is exactly new_type or a less cv-qualified version of new_type, the result is the value of expression, with type new_type.
As a result, the code will always compile and run and the type system will not protect you. But the resulting behavior is undefined. In the case of Beta*b = dynamic_cast<Beta*>((Beta*)p); you tell the compiler to trust that p is a Beta* but this is not true. Dereferencing the resulting pointer is undefined behavior and dynamic_cast cannot protect you from this mistake.
If you try to remove the explicit type conversion, you will get a compiler error. dynamic_cast requires a pointer or reference to a complete type, and void is not a complete type. You will have to find a way to track the actual type pointed to yourself and explicitly convert p to that pointer type before using dynamic_cast. Though at that point, if you already know the type to cast to, it may no longer be necessary.
Consider using a common base type instead or maybe using std::variant or std::any if need be.
If you use a C-style cast to convert to Alpha*, similar to a static_cast before using dynamic cast, then the dynamic cast as no effect. here your code runs because the two classes have the same interface but in reality this is undefined behaviour.
Usually, you want to use dynamic cast to upcast/downcast from/to a base class to/from it's derived class.
For example, if we add a base interface, then convert the void * pointer to this base class and then use dynamic cast to attempt Up-casting, the code works as expected and only print once.
#include <stdio.h>
class Speaker {
public:
virtual void Speak() = 0;
};
class Alpha: public Speaker {
public:
virtual void Speak() { printf("A"); }
};
class Beta: public Speaker {
public:
virtual void Speak() { printf("B"); }
};
int main(){
void *p = new Alpha;
// Convert to base type, using static_cast
Speaker *s = static_cast<Speaker *>(p);
// Attempt Upcasts
Alpha*a = dynamic_cast<Alpha*>(s);
Beta*b = dynamic_cast<Beta*>(s);
// See if it worked
if (a)
a->Speak();
if (b)
b->Speak();
return 0;
}
Outputs: A
You must know the type from which the void pointer was converted from. If you don't know the dynamic type, then you must create the void pointer from the pointer to base. If you don't know the type of the pointer which the void pointer was created from, then you cannot use the void pointer.
Given that the void pointer was converted from Alpha*, you can convert it back using a static cast:
auto a_ptr = static_cast<Alpha*>(p);
You can then use dynamic_cast to convert to a derived type.
if(auto d_ptr = dynamic_cast<DerivedAlpha*>(a_ptr)) {
// do stuff with DerivedAlpha
In case the dynamic type isn't DerivedAlpha, the dynamic cast would safely return null. You cannot dynamic cast away from a type hierarchy. Since Alpha and Beta are not related by any inheritance structure, they cannot be dynamically casted mutually.
I feel this could be explained more simply than what is said already.
Basically, casting from a raw void*, none of the "smarts" of dynamic_cast can apply because it has nothing to go on, it just gives you back the same pointer. You need to have some shared parent class type or something as your pointer type (*p) so it knows how to read the memory and determine actual type.
In your case, you are "lucking out" that the memory layout of Alpha and Beta is the same so calling speak on Beta* ends up calling Alpha::speak(). As others said this is UB and if the classes were more different you would likely seg-fault or corrupt the stack.
I'm working with a library written in C, which does inheritance like so:
struct Base
{
int exampleData;
int (function1)(struct Base* param1, int param2);
void (function2)(struct Base* param1, float param2);
//...
};
struct Derived
{
struct Base super;
//other data...
};
struct Derived* GetNewDerived(/*params*/)
{
struct Derived* newDerived = malloc(sizeof struct Derived);
newDerived->super.function1 = /*assign function*/;
newDerived->super.function2 = /*assign function*/;
//...
return newDerived;
}
int main()
{
struct Derived *newDerieved = GetNewDerived(/*params*/);
FunctionExpectingBase((struct Base*) newDerived);
free(newDerived);
}
It is my understanding this works because the pointer to Derived is the same as the pointer to the first member of Derived, so casting the pointer type is sufficient to treat an object as its "base class." I can write whatever gets assigned to function1 and function2 to cast incoming pointer from Base* to Derived* to access the new data.
I am extending functionality of code like this, but I am using a C++ compiler. I'm wondering if the below is equivalent to the above.
class MyDerived : public Base
{
int mydata1;
//...
public:
MyDerived(/*params*/)
{
function1 = /*assign function pointer*/;
function2 = /*assign function pointer*/;
//...
}
//...
};
int main()
{
MyDerived *newDerived = new MyDerived(/*params*/);
FunctionExpectingBase( static_cast<Base*>(newDerived) );
delete newDerived;
}
Can I expect the compiler to lay out the memory in MyDerived in the same way so I can do the same pointer cast to pass my object into their code? Or must I continue to write this more like their C architecture, and not take advantage of the C++ compiler doing some of the more tedious bits for me?
I'm only considering single inheritance for the scope of this question.
According to Adding a default constructor to a base class changes sizeof() a derived type and When extending a padded struct, why can't extra fields be placed in the tail padding? memory layout can change even if you just add constructor to MyDerived or make it non POD any other way. So I am afraid there is no such guarantee. Practically you can make it work using proper compile time asserts validating the same memory layout for both structures, but such solution does not seem to be safe and supported by standard C++.
On another side why your C++ wrapper MyDerived cannot inherit from Derived? This would be safe (as it can be safe when Derived is casted to Base and back, but I assume that is out of your control). It may change initialization code in MyDerived::MyDerived() to more verbose, but I guess that is small price for proper solution.
For your problem it does not really matter since the "client" code only cares about having a valid Base* pointer: they aren't going to downcast it in Derived or whatever, or copy it.
Say that I have the following code, is it safe to use?
Base class:
class B
{
public:
B(bool isDerived = false) : m_isDerived(isDerived) {}
bool isDerived() { return m_isDerived; }
private:
bool m_isDerived;
}
Derived class:
class D : public B
{
public:
D() : B(true) {}
}
Code:
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b); // Cast the base class into a derived class
if (unknown->isDerived()) // Is this allowed?
// unknown is a D and can be used as such
else
// unknown is not a D and can not be used
Can I safely call unknown->isDerived() even though unknown is really a B in this case?
We make the assumption that unknown NEVER contains anything other than a B* or D* and that we NEVER do anything with unknown until isDerived() have been checked on it.
Edit:
Given the questions I will try to explain the reason why I'm trying to do this:
So essentially I have a Windows tree control which of course can't be directly connected to the c++ tree structure I'm using to store my data. So I have to reinterpret_cast my data to a DWORD_PTR that is stored together with each node in the tree control so I have a connection between the two. My tree structure consists of either the base type (a normal node) or the derived type (a node with more info in it that should be handled differently). The pointers to these are reinterpret_cast:ed and put in the tree control.
Now, when I'm stepping through the tree control I want to act on the nodes which are of the derived type, so I want to reinterpret_cast the DWORD_PTR into a derived type. But to be entirely correct I should reinterpret_cast it to a base type first (I guess?), and then downcast it to the derived type if it is a derived type. However I thought I could make it a bit simpler by reinterpret_cast it into a derived type immediately and then check via the function if it really is a derived type. If it wasn't I do nothing more with it. In my mind the base class data in the pointer should be at the same memory location no matter how much derived it is, but I might be wrong which is why I ask here.
I wanted to make the question clearer by not involving Windows in it, but what I want in reality would be something closer to this:
B* b1 = new B();
B* b2 = new D();
DWORD_PTR ptr1 = reinterpret_cast<DWORD_PTR>(b1);
DWORD_PTR ptr2 = reinterpret_cast<DWORD_PTR>(b2);
D* unknown = reinterpret_cast<D*>(ptr1 /* or ptr2 */); // Safe?
unknown->isDerived(); // Safe?
Essentially no matter what I do it's still unsafe at some level as I must reinterpret_cast the data.
Can I safely call unknown->isDerived() even though unknown is really a
B in this case?
First of all, why would you do this? You could just call b->isDerived() and then do the downcasting.
Now, while premature and likely invalid downcast yields an undefined behavior (and should be universally despised) in this case it should work. Neither B nor D have implicit data members that might change the relative offset of m_isDerived and the address of isDerived member function is constant.
So yeah, it should work. If should is good enough for you.
EDIT: You can place a few tests to make sure offsets are same:
#include <cstddef> // for offsetof macro
#include <cassert> // for assert
#define offsetofclass(base, derived) ((static_cast<base*>((derived*)8))-8)
class Test
{
public:
Test()
{
assert(offsetofclass(B, D) == 0);
// you'll need to befriend Test with B & D to make this work
// or make the filed public... or just move these asserts
// to D's constructor
assert(offsetof(B, m_isDerived) == offsetof(D, m_isDerived));
}
};
Test g_test;
This will get executed on startup. I don't think it can be turned into a static assertion (executed and compile time).
Given your
class D : public B
and
B* b = new B(); // Create new base class
D* unknown = static_cast<D*>(b);
Formally this is Undefined Behavior, but, as long as only B things are accessed there's no technical reason why it should not work. Typically it's done in order to gain access to otherwise inaccessible B things, such as std::stack<T>::c. However there are better ways to do that, including the member function pointer trick.
Regarding
B(bool isDerived = false) : m_isDerived(isDerived) {}
that's very brittle and unsafe.
Instead class B should have a virtual member. Then you can use dynamic_cast and typeid. This is commonly known as RTTI, Run-time Type Information.
However, on the third and gripping hand, the relevant functionality should be made available via class B so that no downcasting is necessary.
As you have pointed out yourself, the only generally correct approach for storing an arbitary hierarchy in a single, opaque pointer is to go via the base class. So, first make your hierarchy:
struct Base { virtual ~Base(){}; /* ... */ };
struct FooDerived : Base { /* ... */ };
struct BarDerived : Base { /* ... */ };
struct ZipDerived : Base { /* ... */ };
You will now exclusively transform between a Base* and whatever raw pointer type you have. Strictly speaking, you can only store pointers in either a void* or a uintptr_t, but let's assume that your DWORD_PTR is wide enough.
If we wrap everything in a function, the upcasting is already taken care of:
void marshal_pointer(Base const * p, DWORD_PTR & dst)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
dst = reinterpret_cast<DWORD_PTR>(p);
}
The return direction is just as easy:
Base * unmarshal_pointer(DWORD_PTR src)
{
static_assert(sizeof(DWORD_PTR) == sizeof(void *), "Not implementable");
return reinterpret_cast<Base *>(src);
}
All the actual polymorphic behaviour should be implemented in terms of virtual functions if possible. Manual dynamic_casts should be your last resort (though occasionally they're appropriate):
Base * p = unmarshal_pointer(weird_native_windows_thing);
p->TakeVirtualAction();
I tried this which didn't work:
void Map::OnLMClick(short xPos, short yPos)
{
SObject* pSObject = pEditWindow->GetSelectedItem();
if (pSObject==SOTile)
{
/* Do */
I tried this as a test:
SObject* EditorWindow::GetSelectedItem()
{
return pSOTile[1]; //pSOTile[1] is a valid pointer, member of EditorWindow
}
SOTile class is a child of base class SObject. So, is it possible to create a Base* to get one of its child's* returned and then have the program react differently depending of what child it returned? If it is the case, how do I then have access to members of it's child that are not members of base?
If your types are polymorphic (i.e. if they have at least one virtual function), you can use dynamic_cast:
Base* pObject = get_object(); // May return a pointer to Derived
Derived* pDerived = dynamic_cast<Derived*>(pObject);
Notice, that dynamic downcasts are sometimes an indicator of bad design. Try to think if a better arrangement of virtual functions in your hierarchy would help.
Without knowing the concrete application domain, it is not possible for me to give more concrete advices.
dynamic_cast operator performs a special checking when a class is polymorhic.
SOTile* pSOTile = dynamic_cast<SOTile*>(pSObject);
if (pSOTile)
{
/* Do */
}
Since SOTile is a pointer to a type that derives from SObject, you should not need to cast at all, since the compiler should be able to automatically resolve an SObject pointer from the derived pointer and then compare the two SObject pointers together (the same way that you can assign a derived pointer to a base pointer without type-casting). Some compilers, like Borland's, support that just fine, eg:
class Base
{
};
class Derived : public Base
{
};
Derived *d = ...;
Base *b = ...;
if (b == d) // <-- compiles fine
However, if for whatever reason your compiler does not allow that, you can manually cast the derived pointer using static_cast (don't use dynamic_cast to cast the base pointer):
if (pSObject == static_cast<SObject*>(SOTile))
If SOTile is not a pointer to a type that derives from SObject, static_cast will fail at compile-time.
I wouldn't recommend to use dynamic_cast. Instead, you can implement that different behavior in different child class. Sometimes called as "template method" pattern
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Conversion between Derived** to Base**
I'm getting back into C++ after several years of mostly Python, and am hitting up against a strongly-typed wall. I think I have a good handle on basic polymorphism and type-casting between pointers of base and derived classes (e.g. Can a pointer of a derived class be type cast to the pointer of its base class?), but here's a stumper: why can't I assign a pointer to a pointer to a derived class to a p-to-p to it's base class?
For more context (and perhaps tips on doing this less pythonishly), here's a reduced version of what I'm trying to do. I want to have a list of pointers to objects (derived from a single class) and a string identifying them (i.e. a map<string, obj*>). A set of components will then pass a list of identifying strings and locations to store a pointer to the corresponding object (i.e. a map<string, obj**>). I should then be able to find the appropriate object by its string id, and fill in the appropriate pointer for subsequent use by the component.
Simplified code to do this is
#include <map>
#include <string>
using namespace std;
class base
{
};
class derived: public base
{
};
typedef map<string, base**> BasePtrDict;
typedef map<string, base*> BaseDict;
int main(int argc, char* argv[])
{
base b1, b2;
derived d;
derived* d_ptr;
BaseDict base_dict;
base_dict["b1"] = &b1;
base_dict.insert(make_pair("b2",&b2)); // alternate syntax
base_dict["d"]= &d;
BasePtrDict ptr_dict;
ptr_dict["d"] = &d_ptr;
for (auto b = ptr_dict.begin(); b != ptr_dict.end(); b++)
*(b->second) = base_dict[b->first];
return 0;
}
This runs into a compile error at ptr_dict["d"] = &d_ptr;. Why? In the C++ paradigm, what should I be doing? Do I really need to do ugly (unsafe?) reinterpret_cast<base>() everywhere?
You're losing the necessary information to be able to cast a base * to a derived *.
Consider the case where derived inherits from multiple base classes, so a cast needs to adjust the pointer value. Then derived *pd = static_cast<derived *>(pb) for a pointer-to-base pb will automatically apply the pointer adjustment.
However derived *pd; base **ppb = &pd; *ppb = *pb will fail to apply the pointer adjustment, so this cannot be legal.
What you should be doing is:
base *b_ptr;
... // existing code
derived *d_ptr = static_cast<derived *>(b_ptr);
Consider what would be enabled if it were permitted to treat a derived** as a base**:
class base
{
};
class derived: public base
{
public:
int boom;
}
void light_the_fuse( base** pb)
{
*pb = new base;
}
int main()
{
derived* pd = NULL;
light_the_fuse( &pd);
pd->boom = 42; // uh oh, `pd` points to a `class base`...
return 0;
}
In order to do a child-to-base conversion the types need to be related. For derived** to base** this implies that derived* is a child of base* which is clearly not true as they're orthogonal pointer types (that happen to point to related classes).
You should be able to solve this with a static_cast rather than reinterpret_cast though:
ptr_dict["d"] = &static_cast<base*&>(d_ptr);
The direct cast derived* to base* is ok, but that's not what you're attempting. You're attempting to do derived** to base**, which isn't an implicit cast. That aside, may I ask why? I'd even go ahead and ask whether you actually need pointers, but double pointers?
It will be much simpler to replace
derived* d_ptr;
with
base* d_ptr;
and use a cast anytime when you may need to apply the exact type of d_ptr but of course the principles of object orientation say that such a case should be quite rare.
You cannot and should not assign a Derived** to a Base** because it is unsafe. If the cast was permitted, then it would allow Derived* to point to types that are not Dervied types. Consider the following:
class Base {};
class Derived: public Base {};
class Other: public Base {};
...
Derived derived;
Derived* derived_p = &derived; // derived_p points to derived.
Derived** derived_pp = &derived_p; // derived_p points to derived.
// derived_pp points to derived_p.
Base** base_pp = derived_pp; // derived_p points to derived.
// base_pp points to derived_p.
Other other;
Other* other_p = &other; // other_p points to other.
*bpp = op; // base_pp points to derived_p.
// derived_p points to other.
If the above code was valid, it would allow Derived* derived = new Other().
Unfortunately, I am not exactly sure what is trying to be accomplished, so I cannot provide an alternative solution.
This is almost similar to Why do I need a reinterpret_cast to convert Fred ** const to void ** const?
Pointer to two different object types are basically incompatible. But, there are exceptions
Derived* to Base*... Derived and Base are related and therefore, conversion is allowed (after typecasting to Base*, the pointer would actually be pointing to an object of Base type
T* to void* - allowed (see the link above)
but there is no reason why D** should be allowed to be converted to B**, because B* and D* are essentially different types.