I want to downcast a base class pointer to a derived class pointer.
I know that dynamic cast is costly so I want to avoid it. In my case, I am fully aware of the actual class the pointer in question points to. Is there a faster way to downcast it than dynamic casting?
I tried to use static_cast but it won't apply here, because there is virtual inheritance in my class hierarchy.
Update:
Thanks for the comments, I now realize that those dynamic cast is not likely to be the bottleneck of the whole program so it is almost a waste of time trying to optimize it.
It does seem that this is exactly what virtual methods are for. Appropriate use of virtual methods eliminates most needs of dynamic casting. And it even works with virtual inheritance.
#include <stdexcept>
#include <iostream>
class Derived;
class Base {
public:
virtual Derived *to_derived()
{
throw std::runtime_error("Nope");
}
};
class Derived : virtual public Base {
public:
Derived *to_derived() override
{
return this;
}
};
class DerivedAgain : public Derived
{
};
int main()
{
DerivedAgain kit_and_kaboodle;
Base *p=&kit_and_kaboodle;
std::cout << (p->to_derived() ? "it works\n":"no it doesn't\n");
return 0;
}
Add a const overload, for const-correctness, if needed.
reinterpret_cast<> is the answer to the basic question of what will downcast without any dynamic checks. It's the strongest (i.e. least-safe) cast this side of a C-style cast.
Related
I'd like to add the extra functionality without changing the existing class.
Say,
class base{
public:
int i;
base(){i = 1;}
virtual void do_work(){ /*Do some work*/ }
};
If I want to add serialization member function to it, I will simply create a derived class
class derived : public base{
public:
void serialize();
};
void derived::serialize(){
cout << "derived class" << endl;
}
And I do need to handle existing base objects,e.g.
int main(){
base a;
derived & b = static_cast<derived &>(a);
b.serialize();
}
This example runs without problems. But I do know the downcast through static_cast is something to be avoided in general.
But I'd like to know if the downcast for this particular use case can be considered safe since the derived class only has one extra member function. Will it has some potential undefined behavior for accessing vtable?
The way you're extending Base you're not making use of the vtable because you have no virtual methods. It may be easier to think of it as Derived has A Base; That you created a new class that contains a Base member variable.
My Suggestion.
Template Function
I personally would go with a template function. You can keep all the work in your original question, and avoid the need of adding virtual calls to your class.
template<typename T>
void serialize_object(T& t)
{
t.serialize()
}
And then based on your example.
Derivied d;
serialize_object(d);
The big benefit is that you're not adding runtime cast here. The compiler will inform you if you pass an object that doesn't have a method serialize.
Go Virtual
If you really want to handle this through a virtual interface do so.
struct Serializable{
virtual void serialize()=0;
virtual ~Serializable(){}
}
class Derived : public Serializable {
public:
void serialize() override;
}
void Derivied::serialize()
{
std::cout << "Yah\n";
}
Then in your code.
Derivied d;
Serializable& s = dynamic_cast<Serializable&>(d);
However, the big concern here is who is the owner of your base class? Did they provide a virtual dtor? If not, then making use of std::unique_ptr or std::shared_ptr could cause you to not deal directly with the interface.
If you can write the serialize function in a derived class without touching private or protected members then you should simply make it a free function. That solves everything.
You can't just cast a base class object to an inherited class. Any members in the inherited class will not have been created and initialized. You need to start with an object of the inherited class.
You can go the other way, of course, and call base class functions from a function of a class inherited from the base, because the base class object will always be there as part of the inherited class object, by definition.
If you have a pointer to the base class, and you build with RTTI, you can use dynamic_cast to cast to an inherited class, but that cast will fail and return NULL if the object is not of the class you're trying to cast to. But usually it's better to call a virtual function than to use dynamic_cast.
I have an array of Base* objects. This holds a bunch of derived objects, some of which may implement an Interface.
struct Base {
virtual void doNotCallThis() { cout << "nooo" << endl; }
};
struct Interface {
virtual void doThis() = 0;
};
// Example derived class
struct Derived : Base, virtual Interface {
virtual void doThis() { cout << "yes" << endl; }
};
int main() {
Base* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
((Interface*)b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
Output:
nooo
I don't know the exact type of b[i] at run time, so I can't cast to Derived (it could be Derived2, Derived3, etc). I also can't use dynamic_cast if that's a solution. All I know is that, by the time I call doThis(), b[i] is a type that inherits from Interface. The way I attempted to call it above causes the wrong function to be called, eg. Base::doNotCallThis().
How can I call it properly?
As other people have pointed out, you would probably do best to find a way to refactor your design so that casting isn't necessary.
But putting that aside, I can explain what's going wrong and how to correctly cast.
The problem with ((Interface*)b[0]) is that since Base and Interface are unrelated the compiler has to do a blind reinterpretive cast. Practically speaking that means in this situation the resulting pointer doesn't actually line up with the Interface part of the object. If you were to try static_cast<Interface*>(b[0]) you would find it doesn't compile - and that's a big hint that it's the wrong kind of cast to be making.
On the other hand, the compiler does know the relationship from Base to Derived and also from Derived to Interface. So as long as you know for sure that the object not only implements Interface but also is a Derived then you can do:
static_cast<Interface*>(static_cast<Derived*>(b[0]))->doThis();
However if your design has multiple different derived types which independently implement Interface then you might not be able to do that unless again you absolutely know what the derived type is at any time you go to make the call. - This is why refactoring it into a better class hierarchy is more desirable, since it's much less fragile and cumbersome to work with.
(As a side note, this issue points out why it's a great idea to never use raw/reintrepretive casts when moving up and down a class hierarchy. At least use static_cast since the can compiler better help you do it correctly.)
Writing an answer with the risk of being downvoted:
If we start with::
struct Base()
{
virtual void SomeFunc();
};
struct Interface
{
virtual void doThis();
}
then to create a bunch of derived functions from Base that are also interfaces, I'd do something like this:
struct BaseInterface : public Base, public Interface
{
// Nothing here - this is just combining Base and Interface
};
struct Base1 : public BaseInterface
{
... add stuff that Base1 has that isn't in Base.
};
struct Derived: public Base1
{
... some more stuff that isn't in Base1
}
And then we use it in Main like this:
int main() {
BaseInterface* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
I have here this abstract base class called base_class defined as it follows:
class base_class
{
public:
virtual ~base_class() = 0 {}
virtual size_t area() const = 0;
protected:
base_class() {}
};
One derived class from with it:
template <typename T> class A : public base_class
{
public:
A();
~A();
size_t area() const;
void display();
(...) etc code
};
And another class still derived from it:
template <typename T> class B : public base_class
{
public:
B();
~B();
size_t area() const;
void set();
(...) etc code
};
Than I have this instantiation and function call:
base_class *p = new A<int>;
p->display();
delete p;
p = new B<float>;
p->set();
(...) code
As you might already have observed, is that the pointer p won't "see" display and set methods.
The question is: when using pointers of type base_class, is there a chance of letting a derived object call derived methods that are only defined in the class that it points to? Thus being able to access display and set methods without having to make them virtual in the base class.
Otherwise we would have to make 2 virtual functions in the base_class, display and set, and that's very inconvenient, because A doesn't have to inherit set method, and B the display method.
You can use dynamic_cast to downcast from base class to derived class, if could not determine the runtime type of the object.
base_class *p = new A<int>;
if (A<int> *pa = dynamic_cast<A<int> *>(p))
pa->display();
delete p;
p = new B<float>;
if (B<float> *pb = dynamic_cast<B<float> *>(p))
pb->set();
If the type of object could be confirmed at compile time, static_cast can do the cast too, but beware: You are telling the compiler that you know for a fact that what is being pointed to really is of that type. If you are wrong, then the cast cannot inform you of the problem (as could dynamic_cast, which would return a null pointer if the cast failed, or throw a std::bad_cast for a reference cast failure) and, at best, you will get spurious run-time errors and/or program crashes.
Anyway, the best practice should be rearrange the inheritance relationship, try to use virtual function, avoid downcasts.
I am not quite sure what you ultimately want to do but its not usually good practice to call a function from the derived class that is not virtual in the base class using a pointer to a base class. As was already mentioned, you can use type casting to achieve this, but you need to check if the dynamic_cast was possible before attempting to call the function.
Have you considered creating a pure virtual function in the base class such as:
public:
virtual void doIt() = 0;
Then you could implement this in the derived classes to call the function you want:
class A
{
void doIt()
{
display();
}
};
class B
{
void doIt()
{
set();
}
};
There's actually no way of accessing the members since for all the program knows it wouldn't have to be a derived class, and could just be the base class. This meaning casting as mentioned in the comments.
A pointer is simply an integer, for 32bit OS's it's a 32 bit int, for 64bit well i guess you could guess right? 64bit integer.
When it comes to typing pointers to actual classes and structures etc, it's up to the API to decide whether or not to display the function, it's more of a helper.
As for the program only knows it's a base class pointer you can only access it's variables. However if you are 100% sure what you are dealing with and you want to save performance here's something somewhat pseudo code.
typedef void (A::*func)(void*);
func f = &A::set;
base_classPointer->*f();
But to be safe and sound either from the beginning make the pointer of the actual class as it seems you will be sure of that it's actually an A class.
Or use yourself of the dynamic, static, casts.
if(B * b = static_cast or dynamic_cast<B*>(mypointer))
Now I do suggest that you use yourself of exact pointer types if you are completely sure of what it's going to be. Or use yourself of the casts. If you are really anxious about performance, try the simple delegate method.
I've got some kind of object factory (template based), that works pretty good for my purposes. But now I've tried to work with class, that derives from both QObject and pure abstract class (interface) and I've got strange run-time errors.
Here the simple picture of this class (Derived)
class Interface {
public:
Interface(){}
virtual ~Interface(){}
virtual int getResult() = 0;
};
class Derived : public QObject, public Interface {
Q_OBJECT
public:
explicit Derived(QObject *parent = 0);
int getResult();
};
and its implementation in derived.cpp:
#include "derived.h"
Derived::Derived(QObject *parent)
: QObject(parent) {
}
int Derived::getResult() {
return 55;
}
When I try to cast void pointer to the Interface, I'll get unexpected (for me) behavior, it can be or runtime error, or other method call (it depends of classes' size).
#include "derived.h"
void * create() {
return new Derived();
}
int main(int argc, char *argv[]) {
Interface * interface = reinterpret_cast<Interface *>(create());
int res = interface->getResult(); // Run-time error, or other method is called here
return 0;
}
Could you explain me why I cannot cast void pointer to interface? And is there any workaround?
Thanks for your responses
Reinterpreting a pointer to a derived class as a pointer to a base class gives undefined behaviour. This is highlighted by multiple inheritance: since there is more than one base class, and the two base subobjects must have different addresses, they can't both have the same address as the derived object. So the pointer returned by your create function points to a Derived, but not necessarily to the Interface subobject. It could point to QObject subobject, or to neither.
The best option is to return Derived* or Interface* from your function; if it must be void* for some reason, then the only well-defined cast you can make is back to Derived*, which can then be converted to Interface* using standard conversions.
By using void* you have thrown away all static and dynamic knowledge of the type; the only way to restore that information is to cast back to the correct type.
Mixing reinterpret_cast with multiple inheritance will likely cause all kinds of problems. In your case, the void* will probably point to the QObject part of the Derived, not the Interface part.
It would probably work better with a dynamic_cast, which can adjust the pointer to point to the correct subobject of the derived class.
Note that in general, the need for these types of casts are a sign of bad design. In your specific case, your factory function needs to return an Interface*. void* in C++ where no C interfacing is involved is just unnecessary and bad.
Apart from all this, factory functions are something of a Java thing, and only required when applying strict design methodology, which often adds more fluff than contributing to clean and bug-free code.
If that doesn't cut it, you'll want dynamic_cast. In Qt for QObjects, you can see if qobject_cast has any merit in your situation.
Here is my test example:
struct base {
virtual ~base(){}
int x;
};
struct derived: public virtual base {
base * clone() {
return new derived;
}
derived(): s("a") {}
std::string s;
};
int main () {
derived d;
base * b = d.clone();
derived * t = reinterpret_cast<derived*>(b);
std::cout << t->s << std::endl;
return 0;
}
It crashes at the line where I print s. Since "b" is a pointer to the derived class, reinterpret_cast should just work. I wonder why it crashes. At the same time, if I replace reinterpret_cast with dynamic_cast, then it works.
Even if b is here dynamically of type derived, you have to use dynamic_cast. This is what dynamic_cast is for, to dynamically convert a pointer of a base class into a derived class at runtime.
reinterpret_cast takes the raw pointer and considers it as being of the derived type. However, because of the virtual inheritance, a slight adjustment must be done to the pointer to point to the correct method dispatch table, and that's precisely what dynamic_cast will do.
Don't reinterpret_cast it, it will cause trouble with multiple or virtual inheritance, like in your case. Wont a simply static_cast do the job here?
To know why, search for implementations of virtual inheritance. A common one is to store a pointer to the base class within the object, so the virtual base does not share the same address than its derived classes. There is a similar case when multiple inheritance is used.
In short, reinterpret_cast can't do much more than casting pointers to ints and back (if there is enough size in the int to contain a pointer).
As the other answers here suggested, you cannot use reinterpret_cast in this fashion because the value of the pointer to base actually differs from the value of the pointer to derived. The valid pointer is deduced at runtime which is why you have to use dynamic_cast. static_cast cannot work, as you don't know at designtime through which intermediate type the most derived class (the one you want to cast to) was derived from the type you have a pointer to.
The real question here should be: I know at design time, how to compute the derived pointer from the base pointer. How can the runtime penalty (of dynamic_cast) be avoided?
Frankly, I don't see a really good option here, but a possible option is to store the pointer to the most derived type in a constant pointer inside the root class, like so:
struct base {
void* const self;
virtual ~base() {}
protected:
base(void* self) : self(self) {}
};
struct derived : public virtual base {
derived() : base(this) {}
}
This is ugly and dangerous, because it sacrifices type safety for performance (if you are really lucky, you get a slight runtime performance out of it). But you will be able to reinterpret_cast your base pointer (the self member of type void*) into a derived pointer.