1: std::vector
does not inherit from _Vector_base
Or rather, not in my standard library implementation. libc++ implements vector like so:
namespace std
{
template <class T, class Allocator = allocator<T> >
class vector
{
...
Sure, your implementation might inherit from a base class, but my implementation does not. This leads to the first error of your interpretation of the "rule":
The C++ standard library can be implemented in a variety of ways, and we really can't make broad, sweeping assumptions or statements about the standard library (the one defined by ISO/IEC 14882:2014
) from one implementation of it.
So, before we get any further, let's remember: we're not going to focus on a single implementation in this answer. We're going to consider all implementations (by focusing on following the definitions in the C++ standard; not the definitions of a particular header file on your hard drive).
2: Okay, yeah, so std::vector
inherits from _Vector_base
But before we continue, let's admit that your implementation might inherit from _Vector_base
, and that's okay. So why is std::vector
allowed to inherit from a base class, but you aren't allowed to inherit from std::vector
?
3: You can inherit from std::vector
, if you want (just be careful)
std::vector
can inherit from _Vector_base
for the same reasons you can inherit from std::vector
: the library implementors are very careful (and you should be too).
std::vector
is not delete
d polymorphically with a _Vector_base
pointer. So we don't have to worry about ~vector()
not being virtual. If you don't delete
your inherited class with a polymorphic std::vector
pointer, then ~vector()
being non-virtual is a non-issue. It's fine. No worries. Let's not fuss about it. No polymorphic delete
s means we don't have to worry about destructors being virtual or not.
But beyond this, the library implementors have ensured that std::vector
is never sliced from using a _Vector_base
reference. Same for you: if you can ensure your custom vector class is never sliced (by someone using a std::vector
reference to it), then you're fine here too. No slicing means we don't have to worry about bad copies being made.
4: Why you shouldn't inherit from std::vector
This has been answered a lot in other questions, but I'll say it again here (and with the focus of the whole _Vector_base
inheritance issue): you (probably) shouldn't inherit from std::vector
.
The problem is that if you do, someone using your custom vector class might polymorphically delete it (they might have a std::vector
pointer to it, and delete
it, which is A Bad Thing if they do). Or they might have a std::vector
reference to your custom object and try to make a copy of it (which would slice the object, which would also probably be A Bad Thing) (I keep assuming a std::vector
reference to your custom object is needed to cause object slicing when copying, because I keep assuming that you're careful enough to never accidentally slice an object with a careless assignment or function call; you would never be so careless, I'm sure, but someone else with a std::vector
reference might be (and yes, I'm being a little facetious here)).
You can control what you do with your code. And if you can control it (carefully) enough to ensure there are no polymorphic delete
s or object slicing, you're fine.
But sometimes you can't really control what others do with your code. If you're working on a team, this might be problematic if one team member unwittingly does one of these things. Which is why I keep bringing up the "be careful" thing.
Even worse, if your code is used by a client, you really can't control what they do, and if they do one of these bad things, you're the one who is probably going to be blamed and tasked with fixing it (have fun refactoring all your code that used to rely on your custom class inheriting from std::vector
) (or just tell the client they can't do that, but you'll probably have a grumpy client who wasted time debugging a weird issue they didn't expect to run into).
Your C++ standard library implementers can get away with this inheritance, though, because they can control things very well: no one is allowed to use _Vector_base
. You can use std::vector
. Only std::vector
. Since you're not allowed to ever (ever) use _Vector_base
, the standard library implementers don't have to worry about object slicing or polymorphic delete
s. And since they're being very careful in their implementation in a controlled environment, things work out just fine.
But even better, by not making assumptions about how std::vector
is implemented, and instead treating it like a (useful) black box, we can make sure that how we use std::vector
is portable to other standard library implementations. If you make assumptions about std::vector
inheriting from some base class, you're going to be limiting the portability of your code.
~vector()
(which you're right isn't a problem if there's no polymorphicdelete
s in the code), one big issue is the potential of object slicing.vector
is such a commonly used type, it might be copied at times in code you don't realize; if you pass in your custom class, that copy will be done on avector
, and will cause object slicing. But those questions you linked to talk about this... – Freezedryvector
to inherit from_Vector_base
? If this were the question, then the focus would be different enough to let this question stand on its own. Otherwise, it's just asking the same question with slightly different words. – Freezedrystd::vector
inherits from_Vector_base
, we can use this fact to decide whether other types should inherit fromstd::vector
. In fact, the two are unrelated. – Seal