multiple inheritance: unexpected result after cast from void * to 2nd base class
It's not a compiler bug - it's what reinterpret_cast
does. The DecoratedSquare
object will be laid out in memory something like this:
Square
Decorated
DecoratedSquare specific stuff
Converting a pointer to this to void*
will give the address of the start of this data, with no knowledge of what type is there. reinterpret_cast<Decorated*>
will take that address and interpret whatever is there as a Decorated
- but the actual memory contents are the Square
. This is wrong, so you get undefined behaviour.
You should get the correct results if you reinterpret_cast
to the correct dynamic type (that is DecoratedSquare
), then convert to the base class.
cast void* to classes with multiple inheritance
The problem with your code is that your shared pointers are null, and therefore behaviour of indirecting through them is undefined.
You can create shared objects using std::make_shared
.
Keep in mind however, that the shared objects are destroyed as soon as last shared pointer is destroyed, at which point any pointers to the objects in your map (if any) are left dangling.
Static cast to base class gives unexpected results when base has a virtual function
The compiler is free to lay out your classes however it likes, presumably your compiler always puts virtual classes at the beginning and any non-virtual classes after that.
You can't rely on any particular ordering of classes.
Vector of elements from multiple classes that have the same base class
When you give a copy of DerivedClass
into a vector containing pointers of BaseClass
, you're essentially downcasting the pointer inside the vector to a BaseClass
object, meaning that that you lose all the DerivedClass
type information (methods, members, etc). While the DerivedClass
contents will still be there, they'll no longer be accessible.
Take the following example:
class MyBaseClass
{
public:
MyBaseClass();
virtual ~MyBaseClass();
void SetValue(const int value);
int GetValue() const;
private:
int m_value;
};
class MyDerivedClass : public MyBaseClass
{
public:
MyDerivedClass();
virtual ~MyDerivedClass();
void SetExtraValue(const std::string &value);
std::string GetExtraValue() const;
private:
std::string m_extraValue;
};
Every variable created of "MyBaseClass" only guarantees that the SetValue
and GetValue
methods are available. Every variable created of MyDerivedClass guarantees that 4 methods are available, the two methods from the base class, and the SetExtraValue
and GetExtraValue
methods.
If you create a vector of MyBaseClass
pointers, you're only guaranteeing that the methods SetValue
and GetValue
are going to be available on the contents of that vector, EVEN IF THE CONTENTS ARE ALL MyDerivedClass
.
Consider this modified version of your example:
QVector<basicClass*> vectorINeed;
basicClass *object= new basicClass(); // <--- Create basicClass instance instead of derivedClass1 instance.
qDebug() << object->basicClass::seta(true);
vectorINeed.append(object);
qDebug() << vectorINeed[0]->basicClass::seta(true);
qDebug() << vectorINeed[0]->derivedClass1::methodInClass1(); // <--- What would happen here?
The compiler cannot guarantee that the object inside the vector is a derivedClass1
object, only a basicClass
object, therefore it cannot guarantee that the methodInClass1
method will be available.
As I see it, you've got three options:
- Change the vector declaration to
QVector<derivedClass1 *> vectorINeed
if you can. Or... - Run your methods against
object
rather thanvectorINeed[0]
. - If you can guarantee that the contents of the vector will ALWAYS be of type
derivedClass1
, you can use thedynamic_cast
function to perform a cast to derivedType before doingmethodInClass1
.
Related Topics
How to Run the Preprocessor on Local Headers Only
Why Doesn't the C++11 'Auto' Keyword Work for Static Members
C++ Static_Cast Runtime Overhead
Conflict Between Copy Constructor and Forwarding Constructor
When to Use C++ Private Inheritance Over Composition
Making a Vector of Instances of Different Subclasses
Traceback a Pointer in C++ Code Gdb
Why Do Two Functions Have the Same Address
How to Handle a Transitive Dependency Conflict Using Git Submodules and Cmake
Open File with Fopen, Given Absolute Path on Windows
How to Load & Call a Vbscript Function from Within C++
Opencv 2.4.3 iOS Framework Compiler Trouble Recognising Some C++ Headers
Std::Async Won't Spawn a New Thread When Return Value Is Not Stored