Need a vector that derives from a vector
Consider this simple code:
class A {
};
class V1: vector&开发者_如何学Pythonlt;A *>{
// my nice functions
};
if I have a instance of V1, then any object derived from A can be inserted into the vector, ok here.
Now, lets say I have two simple classes called B and C both derives from A;
if I have a instance of V1, then both pointers of B and C can be inserted into this vector, I guess this is right to afirm?if so, how can I derive a vector from V1 to make sure only B pointers are inserted?
I was thinking about using templates, but in this case I already know the base of the class and in tempaltes you can use anything, right?Don't know if I am being clear, my english doesn't help...
Would I have to override push_back and other functions to check if the template argument is derived from A?Please, don't need to talk about boost or syntaxes I am using etc... I really just want to understand the concept of this... it is not clear in my mind yet. I have some answers to this but I guess they involve too much of casts to check stuff and I came here to know if there is a better answer to it...
Thanks!
Jonathanps: Can you guys please answer comments I put? sometimes I ask stuff here and then the best answerers come and don't come back :(. Or should I just ask another question instead of comment questioning?
It's not clear from your example if inheritance is needed. You may also not realize it is dangerous, because std::vector does not have a virtual destructor. That means V1's destructor will not be called upon deletion of a pointer to the base class and you may end up leaking memory/resources. See here for more info.
class A {
};
class V1: vector<A *>{
// my nice functions
};
if I have a instance of V1, then any object derived from A can be inserted into the vector, ok here.
Yes, correct.
Now, lets say I have two simple classes called B and C both derives from A; if I have a instance of V1, then both pointers of B and C can be inserted into this vector, I guess this is right to afirm?
Yes, correct.
if so, how can I derive a vector from V1 to make sure only B pointers are inserted? I was thinking about using templates, but in this case I already know the base of the class and in tempaltes you can use anything, right?
Why not use a
std::vector<B*> m_bVector;
for this case? Here's how it would work:
B* bInstance = new B();
A* aInstance = new A();
m_bVector.push_back(bInstance);
m_bVector.push_back(aInstance); //< compiler error
Maybe you have a good reason for inheriting from vector, but I don't see it right now... If you need added functionality, it may be better to have V1 wrap the std::vector, ie:
class V1
{
private:
std::vector<A*> m_aVec;
public:
// use AVec
}
As a general rule of thumb, you shouldn't derive from STL containers. Why not use a vector<A*>
member inside of class V1
?
If you want to store B-pointers in your vector, the best solution is to derive from
std::vector<B*>
Or if you want to have possibility to use your class also with A-pointers, make a template
template<typename T>
class MyVec : public std::vector<T> {
};
MyVec<A*> va; // stores A* and B*
MyVec<B*> vb; // stores B* only
if so, how can I derive a vector from V1 to make sure only B pointers are inserted?
Setting aside that you shouldn't inherit from the STL container (for a number of reasons that may not be obvious), the answer is that you don't. Not really, anyway.
You can make a run-time assertion that only B*
can be inserted:
if(!dynamic_cast<B*>(item))
return false;
But this relies on C++'s RTTI support, which is typically very slow. You could instead use some kind of "roll-your-own" RTTI interface (i.e., a function that returns an enum identifying the class), or perhaps Boost's static assert testing the typeof
the object.
My preference would be this:
template<typename T>
class V1 {
private:
std::vector<T*> _vec;
// ...
};
And then instantiate with a type for T
that makes sense for your use case.
But if you have a case that relies on sometimes there being all B*
s and sometimes all A*
s, then I would submit that your design stinks and should be rethought.
精彩评论