class a //my base abstract class
{
public:
virtual void foo() = 0;
};
class b : public a //my child class with new member object
{
public:
void foo()
{}
int obj;
};
int main()
{
b bee;
a * ptr = &bee;
ptr->obj; //ERROR: class a has no member named "obj"
}
My question is, how can I access the "obj" member when I have a pointer to base class ("a") pointing to child class ("b") object? I know that casting should do the trick but I'm looking for better solutions.
You can use the dynamic_cast<> operator to convert a pointer to a to a pointer to b. The conversion will succeed only if the run-time type of the object pointed to by ptr is b, and will return a null pointer otherwise, so you must check the outcome after converting:
b* p = dynamic_cast<b*>(ptr);
if (p != nullptr)
{
// It is safe to dereference p
p->foo();
}
If you can guarantee that the type of the object pointed to by ptr is b, however, in this case (since no virtual inheritance is involved) you can even use a static_cast<>, which incurs in less overhead because it is performed at compile-time.
b* p = static_cast<b*>(ptr);
// You are assuming ptr points to an instance of b. If your assumption is
// correct, dereferencing p is safe
p->foo();
You'll have to cast down the inheritance hierarchy. Your case is tailor-made for using dynamic_cast to the appropriate type as that allows you to check in a type-safe manner if the object you're trying to cast actually is of the expected type.
In GCC and Clang (and in Visual Studio I think) you can also use the following syntactic sugar
if (Derived* x = dynamic_cast<Derived*>(x)) {
// do something with \c x now that we know its defined
}
and in C++11, using auto type inference, even nicer
if (auto x = dynamic_cast<Derived*>(x)) {
// do something with \c x now that we know its defined
}
and finally if we want to restrict to read-only access
if (const auto x = dynamic_cast<Derived*>(x)) {
// read something from \c x now that we know its defined
}
Note that this nicely limits the scope of x to inside the if clause(s) which is often more convenient if we do multiple successive dynamic_cast after one another using if's and else if's.
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.
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'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!
While fixing a bug in a huge code base, I am observing a strange situation, where the dynamic type of a reference changes from Original Derived type to Base type! I am providing the minimal code to explain the problem:
struct Base {
// some 'virtual' function
protected: // copy constructor
private: // assignment operator
};
struct Derived : Base {
... // There are few more classes between `Base` and `Derived`
... // but for simplicity, I have put direct relation
};
void foo (Base &ref)
{
SomeClass obj;
obj.pVoid = &ref; // pVoid is of void*
// ----> typeid(ref) = Derived
(*funcptr)(obj);
// ----> typeid(ref) = Base !!!
Derived *p = dynamic_cast<Derived*>(&ref); // this fails ... i.e. "p = 0"
}
funcptr is a function pointer (void (*)(SomeClass&)). funcptr can point to so many functions and they have their own call flows, so it would be difficult to debug.
It's very strange that after the call to function pointer, the derived type of ref changes from Derived to Base. To ease my work, I suspected object slicing from Derived to Base, so I made ~Base() as pure virtual and re-compiled the whole source code. But there was no compiler error, which means that there is no object of Base being declared.
What are the potential reasons, that the dynamic type of ref Derived is changed to Base and the dynamic_cast fails later on ?
I don't believe that the above code is like it actually is because the code example doesn't compile! You cannot implicitly convert a Base* resulting from the dynamic_cast<Base*>(&ref) to Derived*.
That said and assuming that the outputs of the typeid() are actually correct there are a few viable explanations of the type ID of the reference changing. All of these indicate an error in the program in some form or the other:
The called function destroys the object e.g. by calling the moral equivalent of dynamics_cast<Base*>(obj.pVoid)->~Base().
The called function constructs a new object at the address pointed to by obj.pVoid using placement new, i.e. something like this: new(obj.pVoid) Base().
Something is overwriting memory, resulting in leaving a Base object in the referenced location.
There are probably more reasons...
Personally, I would gamble on the second case being case, i.e. an object is constructed into the location. Obviously, without seeing the function being called it is impossible to tell.
dynamic_cast (to a pointer) can return 0 if the conversion is ambiguous. To illustrate:
class O {…};
class A : public virtual O {…};
class B : public A {…};
class C : public A {…};
class D : public B, public C {…};
void f(O& p) {
A* const a(dynamic_cast<A*>(&p));
}
void g() {
D d;
f(d);
}
The reason for which the dynamic_cast<> was failing in my specific case is due to deleteing the reference prematurely!
Once a pointer or reference is delete + destructed, then any attempt to downcast it to the original type would result in entering the "undefined behavior" region. In my case the dynamic_cast<> is failing.
void foo (Base &ref)
{
SomeClass obj;
obj.pVoid = &ref;
(*funcptr)(obj); // ----> delete (Base*)(obj.pVoid); in one of the callbacks
Derived *p = dynamic_cast<Derived*>(&ref); // fails => "p = 0"
}
My question is related to RTTI in C++ where I'm trying to check if an object belongs to the type hierarchy of another object. The BelongsTo() method checks this.
I tried using typeid, but it throws an error and I'm not sure about any other way how I can find the target type to convert to at runtime.
#include <iostream>
#include <typeinfo>
class X
{
public:
// Checks if the input type belongs to the type heirarchy of input object type
bool BelongsTo(X* p_a)
{
// I'm trying to check if the current (this) type belongs to the same type
// hierarchy as the input type
return dynamic_cast<typeid(*p_a)*>(this) != NULL; // error C2059: syntax error 'typeid'
}
};
class A : public X
{
};
class B : public A
{
};
class C : public A
{
};
int main()
{
X* a = new A();
X* b = new B();
X* c = new C();
bool test1 = b->BelongsTo(a); // should return true
bool test2 = b->BelongsTo(c); // should return false
bool test3 = c->BelongsTo(a); // should return true
}
Making the method virtual and letting derived classes do it seems like a bad idea as I have a lot of classes in the same type hierarchy.
Or does anybody know of any other/better way to the do the same thing? Please suggest.
Update: b.BelongsTo(a) should detect if the input object type (a) is an ancestor of the current object (b) in the type hierarchy.
This doesn't make sense - the very fact that you can call the function means that the parameter belongs to the X hierarchy, as that is the type of the parameter. Dynamic casts are intended to find out the actual type within a known hierarchy.
The syntax error in your code:
return dynamic_cast<typeid(*p_a)*>(this) != NULL;
is because a typeid is not a type - you simply cannot use it as a type with dynamic_cast like that.
If as Naveen suggests you want to find out if an instance belongs to a sub-hierarchy, use:
if ( dynamic_cast <A*>( some_x_ptr ) ) {
// yes, belongs to A sub-hierarchy
}
Edit: You have:
A <- P <- X
A <- Q <- Y
Then:
A * a = new X;
dynamic_cast <P *>( a ); // not null
dynamic_cast <Q *>( a ); // null
In order for RTTI to work class X needs at least one virtual member function (virtual destructor counts as well). Without virtual member functions the class will not have a vtable generated by the compiler and so when you invoke typeid the latter will not work as you expect.