When a class declares one or more virtual functions, the compiler implicitly adds a V-Table pointer to the class declaration, and thereby, to each object.
For every virtual-function-call, the compiler generates code which reads the function's address from the object's V-Table pointer, and then jumps to that address.
The V-Table pointer of an object is initialized only during runtime, when the constructor of the class is called and the object is created.
So when you create an object without explicitly calling the object's class-constructor, the V-Table pointer of that object is not initialized.
Then, when you call a virtual function of that object, the CPU attempts to read the function's address from the object's V-Table pointer, and a memory access violation occurs.