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.
Related
I am experimenting a little bit with inheritance in C++ and I stepped on a case that I don't quite understand. When I try to compile the code I get:
error: cannot ‘dynamic_cast’ ‘base’ (of type ‘class Base*’) to type
‘class SomeInterface*’ (source type is not polymorphic)
I assume that it is not a proper way of casting, because SomeInterface is not related to Base, but is there a way to make it work? Maybe there something I can add to the class to make static_cast possible? Or is it just a bad architecture and I should rearrange my code to not introduce cases like this one? I'd appreciate any comments or resources I could read to understand this behaviour and possibly learn how to make it work.
class Base
{
};
class SomeInterface
{
public:
void call_me() { }
};
class Derived : public Base, public SomeInterface
{
};
void try_call_me(Base* base)
{
// line below causes an error
SomeInterface* some_interface_instance = dynamic_cast<SomeInterface*>(base);
some_interface_instance->call_me();
}
int main()
{
Derived derived_instance;
Base* base_instance = &derived_instance;
try_call_me(base_instance);
return 0;
}
dynamic_cast requires (except for up-casts) that the base class type used in the argument is polymorphic.
A class in C++ is called polymorphic if it has at least one virtual function. So you need to add one to your Base, for example the destructor:
struct Base
{
virtual ~Base() = default;
};
Polymorphic classes store additional information that is required for dynamic_cast to work at runtime.
However, that is a costly operation to do. Reconsider why try_call_me is expecting a pointer to Base instead of SomeInterface if that is really what it needs.
If you keep it as it is, you also need to add error checking to the dynamic_cast. It will return a null pointer if base doesn't refer to an object whose most-derived object contain a SomeInterface base class subobject that could be side-casted to:
SomeInterface* some_interface_instance = dynamic_cast<SomeInterface*>(base);
if(!some_interface_instance) {
// didn't pass a suitable pointer, error!
// fail here, otherwise there will be undefined behavior!
} else {
some_interface_instance->call_me();
}
(If you use references instead of pointers, dynamic_cast will throw an exception instead of producing a null pointer value.)
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.
In our system, we have
multiple deviceTypes
each deviceType can have a different configuration type
each deviceType will be a library of its own
I'm in a situation where I am forced to use dynamic_cast. I'm wondering if there is a better way to design this ?
what I have is:
// in common code
class Config {public: virtual ~Config(){} };
class Device {
protected:
Config* devConfig;
protected:
virtual void createDevConfig() = 0;
public:
virtual void display() = 0;
};
// Device specific Code
class A0Device : public Device {
protected:
virtual void createDevConfig() { this->devConfig = new A0Config(); }
public:
A0Device() { this->createDevConfig(); }
virtual void display(){
A0Config* config = dynamic_cast<A0Config*>(this->devConfig);
if(!config) std::cout << "Null object\n";
}
};
class A0Config : public Config {};
int main() {
Device* dev = new A0Device();
dev->display();
return 0;
}
Essentially A0Device has its own config type: A0Config, which is composed of other members. A0Device has devConfig defined as Config* in base class. In A0Device::display() - I need to access the devConfig object (as A0Config type). The virtual createDevConfig() ensures the config object will always be of type A0Config in A0Device => Is it safe to use dynamic_cast here ? Is there a better way of designing this ?
If you can support the extra (minimal in general-purpose systems, enormous in real-time/embedded systems) runtime overhead, you can use dynamic_cast<> safely.
However, you must be aware of this "small" detail. Given the expression dynamic_cast<T*>(expr), whenever the dynamic type of *expr is neither T or a subclass of T, the expression evalutates to the null pointer, nullptr. And, of course, dereferencing nullptr invokes undefined behaviour, and will cause a crash on most platforms.
However, it's probably not worth it checking for nullptr if, ando only if, you know your code shall crash on such a situation.
Because C++ is a bowl with both soup and ice cream, potatoes and coffee, and of course, each idea that came through Stroustrup's/the C++ commitee's ears/mind, there are several alternatives:
A downcasting static_cast<T*>(expr), although this has the same issues as casting something to something else that it isn't.
For C people who found it "necessary", reinterpret_cast<T*>(expr) is not necessary in this but it's there.
If you both think that something is engineeringly-perfect if it works, and you know all the types that the object may have at runtime in a single place, you can use a enum for the type with union for holding the data with placement new with explicit destructor calls supercombo.
If data stuff is involved in the problem, you can have something like virtual Config &getConfig() = 0 in the Base, and something like ABC123Config config; Config &getConfig { return this->config; } in the Derived.
For crazyies like me only: Use a C-style/constructor-style cast.
Hope this helps!
You could have a pure virtual function in the base which returns a Config pointer or reference (which I would prefer unless you need a pointer), then have the storage in the derived classes. This question/answers cover the differences between pointers and references: When to use references vs. pointers
The advantage of this design is that anything in the base that needs a Config can use getConfig, while anything that needs to use the derived class can without casting. Plus you don't need to call new and delete.
class Device {
protected:
virtual Config& getConfig() = 0;
...
};
class A0Device {
public:
...
Config& getConfig() {return config;}
...
private:
A0Config config;
};
[Not sure, if I'm missing something here, but it more or less sounds like a design-smell]
Why can't A0Config aggregate Config?
Quite often, hitting upon dynamic_cast is a clue that something is not right in terms of establishing IS-A relationship. In this case A0Configprovides some functionality (getA()) which doesn't fit into its base class Config, perhaps it is violating LSP-Liskov Substitution Principle thereby violating strong IS-A.
Nevertheless, If a class relationship can be expressed in more than one way, use the weakest relationship that's practical – Herb Sutter
... and Sean Parent goes to this extent. Inheritance is the base class of evil
I'm perfectly aware of, that the syntax I'm about to show you, is the mechanism for calling e.g. a base-class method from within a derived class. But in some code I've come across, the same syntax is being used outside the class implementation, and I'm wondering if that is a legal (in the standard C++ sense) construct, and if the resulting behaviour is well defined?
class Base
{
public:
virtual void method(int arg)
{
...
}
};
class Derived : public Base
{
public:
virtual void method(int arg)
{
...
Base::method(arg); // I'm fully comfortable with this...
}
};
int main(int argc, char* argv[])
{
Derived d;
Derived* pD = &d;
pD->Base::method(2); // is this allowed?
...
Legal, yes, but it shows serious misdesign. A class (Derived, in this case) should offer a full interface, be it specific or inherited, and not force its callers to delve into its guts. If clients of Derived would reasonably need to call Base::method instead of Derived::method, then Derived should offer a public method to provide that functionality:
void alternateMethod(int arg) {Base::method(arg);}
Of course, if you really need to call Base::method and cannot change Derived (legacy code or an ill-designed external library), you may have no alternative but using that trick.
To summarise and answer your specific questions: yes, it is a legal construct, and yes, its behaviour is well defined. But redesigning Derived would be much better.
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.