Re: Inherite form stl container classes
On Jun 3, 12:57 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
James Kanze wrote:
[...]
b) As for public inheritance from STL container, there are
two commonly mentioned problems:
b1) STL containers do not have virtual destructors.
This is not really a problem. Just don't delete pointers to
the derived classes through pointers of the base class (and
why would you have any use for such polymorphic container
pointers in the first place). It's about as problematic in
practice as inheriting from std::iterator.
I disagree. There is nothing you could conceivably do with
an std::iterator itself. You'd never have a reference to
std::iterator as a parameter to a function, for example; in
fact, you'd never have a reference or a pointer to an
std::iterator anywhere in any reasonable code. The same
thing cannot be said of std::vector. And while I can't
think of any case where you'd ever dynamically allocate an
std::vector (and thus, invoke delete on a pointer to
std::vector), it's still a risk I'd prefer avoiding.
First, we seem to agree that dynamically allocated vectors are
weird (and would go as far as saying its a smell). That is
_why_ I don't think the absence of a virtual destructor is a
good argument agains public derivation from std::vector.
However, I do see that this very much depends on coding
guidelines and local culture.
Yes. After reading your posting, and thinking it over, I more
or less came to the conclusion that the rule in the guidelines
should be "never allocate a standard container dynamically",
rather than "never derive publicly from a standard container".
This isn't the "generally accepted" rule, however, so it may not
be trivial to get it accepted locally. And if you allow dynamic
allocation of a standard container, then you don't want to
derive from it.
[...]
Well, the more general pattern is this: I like the type system
to distinguish types that have different meaning. Now, a
std::vector<double> can _mean_ many things. I like those
things to be different.
Agreed, but in the domains I work in, those different things
also tend to have different behavior; they're not std::vector,
but rather only support a subset of the operations on
std::vector. (But this may be domain specific. I have
practically no experience in scientic processing, for example.)
Thus:
struct xxx_vector : public std::vector< double > {
// boilerplate code
};
is (in some ways) just an alternative to:
typedef std::vector< double > xxx_vector;
The derivation trick has the advantage that I can choose
whether I want to allow conversions or not. Also (although it
is not clear whether it always is an advantage), I can
overload functions on the semantics of vector.
That's the point that's bothering me. I would have imagined
(being somewhat na=EFve in this domain) that many of these vectors
would have constraints, and that you'd want to replace all of
the non-const functions of vector to enforce those constraints.
At which point, you don't want the client code to be able to
access it as a vector, and avoid your enforcement (and from the
client's point of view, the isA relation to vector doesn't
exist, since there are operations which would be legal on vector
but are not allowed here). Which argues for private
inheritance, with using declarations for the const functions.
I rather suspect that this case is fairly frequent, and that
some means of publicly inheriting the const interface, but
keeping the non-const interface private, might be useful. But I
can't think of what it would look like (and you'd really want
the non-const interface to not be inherited at all, so that it
wouldn't be considered in overload resolution).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34