While writing my first piece of software, I encountered a "strange" behavior when playing with virtual functions, inheritance, and pointers. What I had was a template class State, that had a following function in the public interface
void State::saveState() {};
When the app was first fired up, in order to set a default state, it was calling a setState()
function within the manager function, that roughly goes as follows
case(some enum):
{
mActiveState->saveState();
delete mActiveState;
mActiveState = new SomeStateClassDerivedFromState();
mActiveState->setup(some arguments);
break;
}
Now for the strange thing - the first two lines of this code should cause a run-time error, or something similar. If this function is used to CHANGE the state, then it should be fine. But it was also used for the assignment of some object/memory for State::mActiveState
, which at that point is nullptr
. But it didn't crash for some reason, program executed as expected. But then, I wanted to override the saveState()
function in one of the classes inheriting from State, so I added a virtual tag to the function (body remained empty), and wrote a definition for saveState()
in the derived class. Suddenly, these two lines started crashing the app at startup (as expected). Removing the virtual tag from saveState()
made the app run again.
Why didn't calling a member function and deleting a nullptr
cause a crash until the saveState()
member function was declared as virtual (with empty body, not pure virtual)?
This code recreates the problem
class State
{
public:
void saveState() {};
}
class DState : public State
{
saveState() {};
}
int main()
{
State* state = nullptr;
state->saveState();
delete state;
state = new DState();
}
This worked. The moment I added virtual tag to the saveState()
function in the State class, it crashed on start. My question again, why?