Inheriting from std::vector?

R

Rolf Magnus

lilburne said:
It is unlikely that Pete Becker would derive a class from
a base that has a non-virtual destructure, without some
overriding reason to do so. Because he knows it is a
resource leak waiting to happen,

No, it's not. Polymorphically destroying an object of that class is.
A knife can be a useful tool, and it isn't evil. Hoever, using it to
stab people is. Almost everything can be destructive if you want it to
be.
and that safer alternatives are usually available.

To pretend that you can ensure that the polymorphic deletion
on such a class heirarchy can be avoid just by saying "Don't
do it" is ridiculous.

You could also reinterpret_cast the pointer to char* and delete that
one. It will also result in improper deletion. But why would anyone do
such a stupid thing?
Certain language features ought to be used with caution, IMO
one should learn how to use them properly before you start
to abuse them.

Nope. One should learn how to use them and never abuse them at all.
 
L

lilburne

Alf said:
Well, modest that I am I find it unlikely that either Pete or I don't
know how to use inheritance properly, and I find it unlikely that either
of us would abuse the mechanism.


Then why sanction it for others?

Perhaps you're referring to the OP?

But the OP didn't code inheritance from std::vector; he's, er, inherited
that code...

The OP was proposing deriving 3 additional class from it. If
he can't repair the initial inheritance scheme he can at
least not inherit it, or perhaps reduce the potential risk
by giving the initial inheriting class a virtual destructor.
Perhaps, then, you're referring to your own abusive example code?

The code presented isn't abusive. It simply demonstrated the
problem you are likely to have when you have an inheritance
tree whose base consists of a non virtual destructor. It
could even exist in legacy code, which the deriver is
unaware of, and whose original coder certainly wasn't
abusing the language.
 
L

lilburne

Rolf said:
lilburne wrote:




No, it's not. Polymorphically destroying an object of that class is.
A knife can be a useful tool, and it isn't evil. Hoever, using it to
stab people is. Almost everything can be destructive if you want it to
be.

As day follows night someone will delete an object of the
class polymorphically, there may already be doing so. There
might be code in the system that deletes pointers of the
base class. They may not, nor should they, even know that
the base pointer they are dealing with is of a derived class.

In any case by inheriting from the base you are implicitly
restricting the problem space that your class can be validly
used in, and you have passed a charged on to maintainence
due to a lazy implementation. All future users of the class
have to remember not to destroy via the base, or to call any
method that might do. But you could have avoid the cost by
using composition rather than inheritance.
 
A

Alexander Terekhov

lilburne wrote:
[...]
In any case by inheriting from the base you are implicitly
restricting the problem space that your class can be validly
used in, and you have passed a charged on to maintainence
due to a lazy implementation. All future users of the class
have to remember not to destroy via the base, or to call any
method that might do. But you could have avoid the cost by
using composition rather than inheritance.

No thankyou.

http://google.com/[email protected]
(Subject: Re: blocking inheritance)

regards,
alexander.
 
S

Simon Elliott

Pete Becker said:
You don't do it.

I would have thought that would be quite difficult.

If you work as part of a team of developers, or for a large company
where one team expects to reuse code from another team, you'd have to
carefully document the class. Even if your fellow developers remember to
trace the chain of inheritance right back to the base class and check,
how many of them will know that std::vector doesn't have a virtual
destructor? (I didn't know until I read this thread.)

If you're a one man band, you still might post some of your code on the
internet, sell it to somebody, or be very busy and need to subcontract a
project.

Even if you know (somehow) that you will never do the above, you might
need to do a rush job and think: "OK, I can inherit from my XYZ class,
job done and dusted." Then you find yourself in the debugger at three in
the morning, drinking jolt cola or black coffee.

All the same, there are times when I would like to be able to inherit
from a std::vector or other container. I tend to typedef my STL
container declarations:

typedef std::vector<int> CsectorList;

But then I find that I can't forward declare them, because you can't
forward declare a typedef. If I could safely do:

class CsectorList:public std::vector<int>{};

Then I could forward declare this as:

class CsectorList;

Anyone got any ideas for safely achieving this?
 
L

lilburne

Simon said:
I would have thought that would be quite difficult.

You know, I know it, ...
All the same, there are times when I would like to be able to inherit
from a std::vector or other container. I tend to typedef my STL
container declarations:

typedef std::vector<int> CsectorList;

But then I find that I can't forward declare them, because you can't
forward declare a typedef. If I could safely do:

class CsectorList:public std::vector<int>{};

Then I could forward declare this as:

class CsectorList;

Anyone got any ideas for safely achieving this?

The question I'd ask is why you want to typedef the thing,
other than to avoid adding #include <vector>. I suppose it
might make it easier to turn it into a std::list, or
whatever, at some later stage. The problem is that you
haven't really hidden the fact that its a vector and haven't
stopped clients from using vector specific operations. I've
been there.

Another motivation I've seen is when someone inherits a
container and adds application specific operations to the
new class. The problem with this is that clients can still
treat it as a bare std::container circumventing any
application specific invariants you might want to impose.
IOW you don't protect access to the container.

Personally I'd either seperate the container specific
element from the application specific operations, or use the
has-a relationship between the classes. I prefer the later.
The result is I believe more robust over time.
 
S

Simon Elliott

lilburne said:
The question I'd ask is why you want to typedef the thing,
other than to avoid adding #include <vector>. I suppose it
might make it easier to turn it into a std::list, or
whatever, at some later stage.

There's the clarity issue as well. This is discussed quite well here:

http://www.gotw.ca/gotw/046.htm

But I'm fairly sure that you still have to #include <vector>. More
unpleasantly, if your container is a
std::vector<large_nontrivial_class>

you also need to #include "large_nontrivial_class.h"

So classes which didn't need to know about either std::vector or
large_nontrivial_class still need both includes.

If we were to inherit from std::container<large_nontrivial_class>, the
inherited class could be forward declared and neither of these includes
would be necessary.
The problem is that you
haven't really hidden the fact that its a vector and haven't
stopped clients from using vector specific operations. I've
been there.

Another motivation I've seen is when someone inherits a
container and adds application specific operations to the
new class. The problem with this is that clients can still
treat it as a bare std::container circumventing any
application specific invariants you might want to impose.
IOW you don't protect access to the container.

You could always inherit from it privately, but see below.
Personally I'd either seperate the container specific
element from the application specific operations, or use the
has-a relationship between the classes. I prefer the later.
The result is I believe more robust over time.

Yes, and this would also be safer if the container had not got a virtual
destructor. On the other hand, there may be some usefulness in exposing
the underlying container, as this allows users to apply all the generic
algorithms from the standard library to your class.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,121
Latest member
LowellMcGu
Top