I am wondering what really happen in pointer casting when we are using downcast and upcast.
I have 2 question. First 2 of them is the comment. Q3 is in the end.
#include<iostream>
using namespace std;
class A{
public:
virtual void f()
{
cout<<"A"<<endl;
}
};
class B: public A{
public:
virtual void f()
{
cout<<"B"<<endl;
}
};
int main()
{
A* pa =new A();
B* pb =new B();
A* paUpcast= new B();
/*
Q1:
Is the line above equivalent to the following?
A* paUpcast = (A*) B;
*/
B* pbDowncast=(B*)paUpcast;
/*
Q2:Why we cannot use the following 2 code;
B* pbDowncast=new A();
B* pbDowncast = (B*) pa;
*/
pa->f();
pb->f();
paUpcast->f();
pbDowncast->f();
return 1;
}
Q3: I am trying to summary a rule to infer what will happene if we use the virtual function and pointer cast together, but I just cannot figure it out.
Originally, I think virtual function will lead us to where the pointer really pointed out.
Therefore, when we type
A* paUpcast= new B();
paUpcast->f();
the second line will display “B” if A.f() is virtual function, because paUpcast is actually point to B object
However, when we type
B* pbDowncast=(B*)pa;
pbDowncast->f();
and it will display “A” instead of “B”, which make the contradiction happen.
Can anyone explain or show me some tip? Thanks alot
I would try to explain how i understand it. the tip that helps me is to think about lego pieces.
In your case, we have two lego pieces, one named
Aand another namedB… but just imagine that theBpiece is a piece formed by attaching two pieces, one of the pieces is the same type ofA:Then, you use pointers to reffer each of the lego pieces, but each piece has its own shape, so, just imagine:
Note that the
paUpcastpointer is a pointer of typeAbut holding a piece of typeB, theBpiece is different from theAone, as you can see is a piece slightly greater than its base.This is the upcasting you’re talking about, the base pointer is like a wildcard that can hold anything related downwards on the inheritance tree.
Well, assuming that you really want to write this:
A* paUpcast = (A*) new B();yes, it is. You create a new instance of theBclass and stores it into a pointer toAclass, converting the new instance before assigning into the pointer doesn’t changes the fact that it will be stored into a base class pointer anyway.Remember the lego pieces. What happens while doing
B* pbDowncast=new A()?:Creating a new base clas instance and storing it into a pointer to derived class, you’re trying to treat the base as derived, if you look closely the lego piece doesn’t fit! the
Apiece lacks of the extra stuff necessary to be considered of theBkind; all this stuff “is stored” into the extra part of the lego piece,B = all the A stuff plus something more:What would happen if you try to call a method that only the
Bclass has? Having aBpointer you’re allowed to call all theBmethods, but the instance you created is fromAkind that wouldn’t have theBmethods, it wasn’t created with all this extra stuff.It doesn’t ressembles a contradiction to me, remembering the lego pieces, the
papointer is pointing to a piece of typeA:This piece lacks of all of the
Bstuff, the fact is that lacks thef()method that printsBon the standard output… but it have a methodf()that printsAon the output.I hope it helps!
EDIT:
No, i don’t agree. Downcasting isn’t inappropiate at all, but it would be inappropiate depending on its use. Like all the C++ tools, the downcasting has an utility and scope of use; all the trickery that respect the good use would be appropiate.
What would be a good use of the downcasting tool then? IMHO anything that wouldn’t break the code or the program flow, maintaining the code as readable as possible and (the most important for me) if the programmer knows what is he doing.
Downcasting taking a possible inheritance branch is a common practice after all:
But it would be troublesome with a more complex inheritance tree:
To deal with this, you can get use of the
dynamic_castBut
dynamic_castis well known by it’s lack of performance, you can study some alternatives todynamic_cast, like internal object identifiers or conversion operators but in order to stick to the question, the downcasting isn’t bad at all if it is used correctly.