开发者

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!

Jonathan

ps: 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜