Reputation: 51
class Parent
{};
class A_child : public Parent
{
void A_method();
};
class B_child : public Parent
{
void B_method();
};
void main()
{
A_child a;
Parent *p = &a;
B_child *b = (B_child*)&p;
b->B_method();
}
This piece of code is in C++. It is a logical error as we are trying to cast a "Cat" into a "Dog". But it works. Can anyone explain why and how?
Upvotes: 0
Views: 129
Reputation: 2981
This is likely but not guaranteed to not cause an error because your B_method is effectively static
.
As soon as the method becomes virtual
(and now requires the class pointer for access to the vtable to look up the function address), accesses class data, or you sneeze or look at the compiler funny, you will be dealing unbound memory access.
And I should stress that while dereferencing the class pointer is not required by a hypothetical compiler, it is allowed, and could be required by any particular compiler implementation.
Further reading...check out the accepted answer Difference between Object and instance : C++ Your class pointer is unlikely to be looked at until you access instance data
associated with a particular instance of the class.
Or...another way to put all this. If you can tack on static
in front of your function declaration, calling it with an invalid pointer might work.
See also:
class MyClass
{
public:
int doSomething(int x)
{
printf("%d", x);
return x;
}
};
int main()
{
MyClass *pMyClass = nullptr;
pMyClass->doSomething(42);
}
Upvotes: 3
Reputation: 238461
Can anyone explain why and how?
Parent
is a base of B_child
and so the conversion from the type Parent *p
to B_child*
is well formed. However, the behaviour of accessing the pointed object through this converted pointer is only defined if p
actually does point to a base sub object of a B_child
instance.
The precondition does not hold, and so the behaviour of the program is undefined. Possible behaviours include, none of which are guaranteed:
- working
- not working
- random output
- non-random output
- the expected output
- unexpected output
- no output
- any output
- crashing at random
- crashing always
- not crashing at all
- corruption of data
- different behaviour, when executed on another system
- , when compiled with another compiler
- , on tuesday
- , only when you are not looking
- same behaviour in any or all of the above cases
- anything else within the power of the computer (hopefully limited by the OS)
Never static_cast
, reinterpret_cast
or C-style cast an expression to another type unless you can prove that the cast is correct. You can use dynamic_cast
in a case where you're unsure.
Upvotes: 5