Welcome to the Wonderful World of Undefined Behavior! According to the C++ spec, the behavior of this problem is undefined, so what you're seeing might work on your system but crash on others, or vice-versa.
Practically speaking, what's happening here is probably an artifact of how the compiler generates code for member functions. Typically, a member function that looks like this:
void doSomething() {
cout << "Hello!" << endl;
}
would probably be compiled as if it were a free function like this:
void Base_doSomething(Base* this) {
cout << "Hello!" << endl;
}
In that sense, when you write
bf->doSomething();
the compiler treats it as if you've written
Base_doSomething(bf);
and nothing bad happens, because Base_doSomething
doesn't reference the this
pointer, which is where all the bad things happen.
Now, this is very brittle. If you try to read any of the data members of the Base
type, this code will crash because then you are reading from a bad pointer. Similarly, if doSomething
were a virtual
function, you'd get a crash because calling a virtual function (typically) requires reading from the receiver object to find the vtable to determine which function to call, and a dangling pointer will then lead to a bad memory access.
So, to summarize:
- This code leads to undefined behavior, so the particular behavior you're seeing isn't guaranteed to happen or work across platforms.
- Although syntactically
bp->doSomething()
looks like a pointer dereference, it might not actually involve a pointer dereference.
- Member functions are typically compiled as free functions that have an "implicit
this
" pointer passed as a first argument.
- Virtual functions work differently than this, so you'd expect to see different behavior there.
Hope this helps!