downcast problem in c++
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public :
void f();
void g();
int mBaseData1;
};
class Derived : public B开发者_如何学Goase
{
public :
int mDerivedData1;
};
void main()
{
Base* base = new Base();
Derived* derived = (Derived*)(base); // DownCast
derived->mDerivedData1 = 6;
cout<< derived->mDerivedData1<<endl; // Result = 6;
}
in this code new base()
allocate memory in heap
and Derived* derived = (Derived*)(base)
cast base to derived
how we can use mDerivedData1? i cant find where we allocate memory for mDerivedData1 or when we call constructor of Derived for allocate mDerivedData1 ?
The reason you can't find where memory for mDerivedData1
was allocated is because no memory was allocated. You have performed an invalid type-cast. The thing stored in base
is a pointer to a Base
instance. Using a type-cast to tell the compiler that it's actually a pointer to a Derived
instance doesn't make it so (but the compiler will believe you anyway because you're the one in charge). The object is still just a Base
. If you want a Derived
, then you'll need to instantiate a Derived
. You can use dynamic_cast
to convert the Base
pointer into a Derived
pointer.
Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
derived->mDerivedData1 = 6;
It will work correctly if you change:
Base* base = new Base();
to:
Base* base = new Derived();
but in general you should never downcast unless you are really sure you know what you are doing, and even then it's usually a sign of a very bad design.
You are really overwritting some part of the heap that is not part of the original base
object. This could overwrite another object on the heap, or other unexplained happenings could occur.
C++ lets you do what you tell it to do for the most part. You are shooting yourself in the foot. :)
Your program exhibits undefined behavior. You cannot access mDerivedData1
because you don't actually have an instance of Derived
.
You can cast an instance of a child class to a base class, but you cannot (well... should not) cast an instance of a base class into a child class.
Edit:
If you are confused about how casting works:
An object never actually changes during a cast -- in truth an object is really just a contiguous block of memory. When an object is cast, the only thing that changes is how the program sees and works with the object.
That's why casting an instance of a base object to a child object results in undefined behavior; the runtime interprets the base object as a child object and uses the pointer for the object as a starting point for referencing data of the object. If a field that is defined on the child class is used on a base object cast as the child object, the program will reference memory that is not part of the instance. If this referenced memory happens to be unused by the rest of the program, things might seem just fine (for a little while), but if the memory is used by another object, strange things could happen in your program -- the other object might have a value changed that it shouldn't have, or worse. And this is just when dealing with heap allocated objects; try this with a pointer to a stack allocated object and you could totally derail your entire program -- assuming you don't segfault.
So in general, if B derives from A:
- You can cast an instance of B to A
- You can cast an instance of B that is already cast as an A back to B, but this may indicate sloppy architecture of your program.
- You cannot (should not) cast an instance of A to B, as this will result in undefined behavior.
精彩评论