I disagree. I agree that the virtual destructor problem is a minor
thing. However, a much more major thing is the fact that Cards
probably has class invariants that vector<Cards> doesn't. For a start
there should perhaps be a separate Pack class and Hand class. Exposing
the whole vector interface may cause difficult to track down bugs in
the future, unless the Cards class is only used internally.
Actually I agree with you. A restricted interface is typically necessary
though you can employ "using" statements to privatize public base class
members if you want (unbeknownst to many developers though it's an ugly
approach IMO). My real beef lies with those pedantic arguments that state
you absolutely must not do it:
a) Because of the virtual destructor issue
b) Because it's a "concrete" class not intended for further derivation
Well item a isn't an issue if properly controlled and item b is just a
pie-in-the-sky philosophy. Why should someone write a regular (non-member)
"toupper()" function for instance when it's cleaner to derive "MyString"
from "std::string" and implement a member function that does this instead.
It fits naturally into the OOP model and is therefore much cleaner
(especially for strings and vectors which are a staple of most projects).
Therefore, for a generic "vector" class it's ok to derive from it in many
circumstances (to add additional functionality in a controlled environment
for instance). When you need a restricted interface then you can consider
encapsulation.