C++ check if object is a descendant of a given superclass - c++

I have a pointer to an object, I want to know if that object is either of type of a given class or of type that is a subclass of the given class in C++.

Use dynamic_cast:
class A {
public:
virtual ~A() = default;
};
class B : public A {
};
B * obj = new B();
auto obj2 = dynamic_cast<A*>(obj);
if (obj2 != nullptr) {
std::cout << "B is an A" << std::endl;
}

The pointer you start with must have a type. Let's say that type is T*. Let's say the "given class" is G. I think (although I may be wrong) that it's the complete type of the object that you want to know about, not the relation between the types T and G.
If T is a class type with at least one virtual function, then you can do the test you want on a pointer ptr like this:
if (dynamic_cast<G*>(ptr)) {
// then the complete type of your object is either G or a subclass
} else {
// it isn't
}
If T is not a class type, or if it doesn't have a virtual function, then what you want to do is not possible. You'll have to find a more useful static type for the pointer.
If all you want to know is whether G is "either a base of or the same as" T then you don't need dynamic_cast or for there to be a virtual function. You just need std::is_base_of.

Related

Checking the original type of a converted object

I wanted to know if it's possible to get the original type of an object when held through a pointer to base class.
For example:
class Base {
virtual void f() = 0
};
class Derived: public Base {};
Base * ptr=new Derived;
//if I use
cout << typeid(ptr).name(); //prints Base*
I want it to print the original type "Derived". Is there a way to do it?
Yes, the static and dynamic type of ptr are both Base *. However, for *ptr, the situation is different. The static type is Base &, but the dynamic type is Derived &. So that's what you want to test:
cout << typeid(*ptr).name();
You can try with dynamic_cast
if(Derived* d = dynamic_cast<Derived*>(b1))
{
std::cout << "downcast from b1 to d successful\n";
d->name(); // safe to call
}
Be careful as this is often seen as a bad practice, and you shouldn't really do it. You don't need the derived type class, try to think in terms of interfaces.

Does a static_cast of a derived object to base always select most derived object?

In the artificial example below, if I static_cast to the base class, when I call the setSnapshot() function it still calls the actual object setSnapshot(). This is what I want to happen. My question is can I always rely on this to work?
In code I am working on, we have this class hierarchy and in the b class there are macros used which static cast to the b type. This is to downcast from a base type so that specialised function in b can be called.
#include <iostream>
class a {
};
class b: public a {
public:
virtual void setSnapshot() { std::cout << "setting b snapshot\n"; }
};
class c : public b {
public:
virtual void setSnapshot() { std::cout << "setting c snapshot\n"; }
};
int main() {
a* o = new c;
//specifically casting to b
static_cast<b*>(o)->setSnapshot(); //prints setting c snapshot - what I want to happen
delete o;
return 0;
}
The title suggests that you're misunderstanding what the case does. new c creates an object of type c, and it will remain a c until it's destructed.
If you were to cast it to an a, you'd create a copy. But yu're only casting pointers. That doesn't affect the original object. That's still a c, and that's why you end up calling c::setSnapshot().
As long as a function is virtual in the statically known type a call of it will go to the override that is most derived.
For single inheritance this can be understood as a search for an implementation up the base class chain, starting in the most derived class.
In practice, for C++, the dynamic search is not done, and the effect of the search is instead implemented as a simple table lookup.

when a base class pointer point to a base class object whether the compiler will use dynamic binding?

I know that when use a base class pointer which point to a derived class object to call a virtual function, the compiler will use dynamic binding to call the derived version.
But when use a base class pointer which point to a base class object to call a virtual function, does the compiler use dynamic binding or static binding to call the virtual
function?
For example:
class Base
{
public:
virtual void show()
{
cout << "base class";
}
}
int main()
{
Base *pb; //Base class pointer
Base b; //Base class object
pb = &b;
pb->show(); //Is static binding or dynamic binding?
}
Because My English is very bad, so I want to make my question as simple as possible, but I will describle my question in more detail in follow:
Actually the problem stems from that I am summarizing how to trigger dynamic binding.
At first I summary the trigger condition are:
the function must a virtual function.
must use pointer or reference to call the function.
The two trigger condition cause the problem that I asked:
"when a base class pointer point to a base class object whether the compiler will use dynamic binding?"
I have google for search answer, and I find a fragment (the demo is here):
struct A {
virtual void f() { cout << "Class A" << endl; }
};
struct B: A {
//Note that it not overrides A::f.
void f(int) { cout << "Class B" << endl; }
};
struct C: B {
void f() { cout << "Class C" << endl; }
};
int main() {
B b; C c;
A* pa1 = &b;
A* pa2 = &c;
// b.f();
pa1->f();
pa2->f();
}
The following is the output of the above example:
"Class A"
"Class C"
According to pa1->f() will output Class A, I summary third trigger condition:
3.function in base class must be overridden in the derived class.
Now according to the three trigger condition, when use a base class pointer which point to a base class object to call a virtual function, the compiler will use static binding to call the virtual function, because the virtual is not overridden.
But when use a derived class pointer which point to a derived class object to call a virtual function, it will use dynamic binding, because the virtual is overridden.
It made me very confused.
It can choose whichever, or neither, depending on how smart it is and how well it can detect. The rule is polymorphism must work. How this is achieved is an implementation detail.
If the same end-result can be achieved with both dynamic or static binding, as is the case here, both are valid options for the compiler.
In your case, the function doesn't have to be called at all - the generated code could be just as well identical to code generated by
int main()
{
cout << "base class";
}
I guess it depends on compiler optimization. Compiler might be clever enough to figure out that Base::show is always the one called or it might not. You can look at the disassembly to find out. You can force static-binding with b->Base::show()
Short answer: No. At least in theory not. Because in theory, the compiler does not know wether the pointer points to a Base, a Derived or to YetAnotherDerived object. Therefore it has to apply the same mechanism regardless of the dynamic type of the object.
But: In practise, compilers have optimizers, capable of identifying some use cases where the dynamic type is known. I your case it can detect the aliasing, meaning it knows that pb points to b and that it is a local variable and cannot be changed concurrently, so it knows that in fact you are calling b.show() and will abbreviate the output to reflect that fact and get rid of the virtual dispatch. Similar optimizations are possible e.g. in this code:
auto pb = make_unique<Base>();
pb->show();
But as any optimization it is up to the compiler if it applies them - the standard says virtual dispatch happens even if the pointer points to a Base object, and that's it.

Accessing child class members using pointer to a base abstact class

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.

dynamic_cast of void *

I need to use dynamic cast void*
void *target = (MYClass*)target;//I am storing initially(to implment delegate mechanism)
....
delegateClass *delegate = dynamic_cast<delegateClass*>(target);
It is giving error cannot convert void*, I cannot use below code... since it is a delegate mechanism
delegateClass *delegate = dynamic_cast<delegateClass*>(((MYClass*))target);
How to get the type of target and implement... If i use typeid() i can get the name of the class but how to use typeid in the above equation instead of (((MYClass*))target).
You cannot use dynamic cast unless the original type of the variable had a vtable (ie, had virtual functions). This is because dynamic_cast requires run-time type information, which is recorded in the vtable; if the vtable is missing, the compiler doesn't know what type the object is.
You should declare a base class with a virtual destructor, and use pointers to this base class rather than void *.
If you must pass the object as a void * then you should use
delegateClass *delegate = static_cast<delegateClass*>(((MYClass*))target);
as there is no class relationship between the void *target and delegateClass. Here you are saying that you know that target _is_a_ delegateClass.
However this idiom is usually used for passing code through standard C interfaces and back.
I'm in a similar situation and being learning c++ style type casting. I referred to this llink http://www.cplusplus.com/doc/tutorial/typecasting/
From this what I can interpret is that the purpose of dynamic_cast is to ensure that the result of the type conversion is a valid complete object of the requested class. So when we try to convert from derived class to base class the conversion is smooth. But the vice versa is not true.
class CBase { };
class CDerived: public CBase { };
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived
Now for that to work the base class should be polymorphic i.e. it should have a virtual function. When a class is polymorphic, dynamic_cast performs a special checking during runtime to ensure that the expression yields a valid complete object of the requested class. Have a look here.
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast<CDerived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast<CDerived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
}
Here the code tries to perform two dynamic casts from pointer objects of type CBase* (pba and pbb) to a pointer object of type CDerived*, but only the first one is successful. Even though both are pointers of type CBase*, pba points to an object of type CDerived, while pbb points to an object of type CBase. Thus, when their respective type-castings are performed using dynamic_cast, pba is pointing to a full object of class CDerived, whereas pbb is pointing to an object of class CBase, which is an incomplete object of class CDerived so it returns a null pointer to indicate the failure.
So I'd suggest you to make use of the static_cast which offers bi directional type casting i.e. from derived to base class and also from derived to base class. But in that case programmer needs to ensure that the conversion is safe becasue the type checking is not performed at run time as in case of dynamic_cast.
In your code here either make target to point to deligate class object before conversion(but make sure Myclass is polymorphic) otherwise you can go for static_cast.
This explaination is based on my very recent reading on the topic and I'd suggest you to refer to Effective C++ for more insight about this. I hope this will help. :)