Destructors run in reverse order of construction. When a derived object is destroyed, the derived destructor runs first, then the base destructor. This ensures the derived class can clean up its members while the base part is still valid.
After the derived destructor finishes, the base destructor cleans up base members. You never call the base destructor explicitly. The compiler chains destructors automatically, just like it chains constructors.