Reputation: 1591
In the Code Below there are Two Classes. One Object of type two is created and then it is assigned to pointer of class one.
On Calling the out function, the out function of the class one is called.
#include<iostream>
using namespace std;
class one
{
public :
void out()
{
cout<<"one ";
}
};
class two
{
public :
void out()
{
cout<<"two ";
}
};
int main()
{
two dp[3];
one *bp = (one *)dp;
for (int i=0; i<3;i++)
(bp++)->out();
}
OUTPUT
one one one
Output according to me should be two instead of one. When we created the object of type two, the memory location of that object contained the address of the function of out of class two, then why on assignment, out of class one is called ?
EDIT - moreover even if we change the name of function in class two, the output is not changed.
Upvotes: 2
Views: 203
Reputation: 36011
Since your out()
method is not declared virtual
it is dispatched on the static type of the object not the runtime type of the object.
Also, there is no subtype relation between the two classes so it is incorrect to assign the pointers in this way.
Upvotes: -3
Reputation: 101456
The output on your machine may have been "one one one" but it could just as easily have blown up, gone & gotten you ice cream, or launched the missiles. Your code evokes Undefined Behavior.
class one
/*...*/
class two
/*...*/
Note that one
and two
are completely unrelated classes. You are not deriving two
from one
, or vice versa. They are entirely different types.
Because of this...
two dp[3];
one *bp = (one *)dp;
for (int i=0; i<3;i++)
(bp++)->out();
This code evokes Undefined Behavior*. bp
does not point to an object of type one
, it points to an object of type two
. You cannot cast pointers in this way given the above code.
(* Note: The Undefined Behavior was when you tried to call a one
method when the object was actually a two
. Casting itself does not evoke Undefined Behavior.)
This cast syntax you are using, (one *)dp
is a C-style cast, which in this instance boils down to the equivilant of reinterpret_cast<one*>(bp);
. It would be best to use reinterpret_cast
when that's what you really intend to do, if for no other reason than to write self-documenting code.
If you really are trying to get a one*
from a two*
, you have two options.
one
from a two
or vice versa.In your case, since you're looping over an array of one
objects and trying to execute two
methods through those pointers, your best bet is probably #1 above.
class one
{
public :
virtual void out()
{
cout<<"one ";
}
};
class two : public one
{
public :
void out()
{
cout<<"two ";
}
};
Now your loop will work and the code will emit "two two two" instead of whatever random behavior you actually saw.
Upvotes: 1
Reputation: 66371
It's not uncommon for a novice to assume that all C++ member functions "belong" to an object.
As you noticed, they don't.
Conceptually - the precise procedure is a compiler implementation detail - your out
member functions are transformed into "free" functions that look like these:
void one_out(one* this) { cout << "one"; }
void two_out(two* this) { cout << "two"; }
For non-member functions, that's all that's needed.
When the compiler sees
(bp++)->out();
it knows that bp is a pointer to one
(it doesn't know that you lied), and so it calls
one_out(bp++);
because that's what compilers do.
Upvotes: 4