When a function is virtual, calling that function treats the class as to what its "actual" type is.
When a function is non virtual, calling it treats it as what it "appears" to be.
Example:
1 2 3 4 5 6 7 8 9
Base* foo = new SubA;
// since foo "actually" is a SubA, this will call SubA::VirtualFunction
foo->VirtualFunction();
// since foo "appears to be" a Base (it's a Base*, not a SubA*), the compiler
// can't tell at compile time whether or not it actually points to a SubA
// so this calls Base::NonVirtual
foo->NonVirtual();
Destructors are the same way:
1 2 3 4 5 6
Base* Test2 = new SubA; // read: no need to cast here
delete Test2;
// if Base's dtor is virtual, then the "actual" type's dtor is called (in this case: SubA's dtor
// but if it's not virtual, only Base's dtor is called because the object "appears to be" a Base.