考虑这个简单的代码:
class A {
};
class V1: vector<A *>{
// my nice functions
};
如果我有V1的实例,那么从A派生的任何对象都可以插入到向量中,好了。
现在,假设我有两个名为B和C的简单类,它们都来自A;
如果我有V1的实例,那么B和C的两个指针都可以插入到这个向量中,我想这是正确的吗?
如果是这样,我如何从V1导出一个向量以确保只插入B指针? 我正在考虑使用模板,但在这种情况下,我已经知道了类的基础,并且在tempaltes中你可以使用任何东西,对吗?
不知道我是否清楚,我的英语没有帮助...
我是否必须覆盖push_back和其他函数来检查模板参数是否派生自A?
请不要谈论我正在使用的提升或语法等等......我真的只是想理解这个概念......我脑海里还不清楚。我有一些答案,但我猜他们涉及太多的演员来检查东西,我来到这里知道是否有更好的答案......
谢谢!
乔纳森
答案 0 :(得分:3)
从您的示例中不清楚是否需要继承。您可能也没有意识到它是危险的,因为std :: vector没有虚拟析构函数。这意味着在删除指向基类的指针时不会调用V1的析构函数,最终可能会泄漏内存/资源。有关详细信息,请参阅here。
class A {
};
class V1: vector<A *>{
// my nice functions
};
如果我有V1的实例,那么从A派生的任何对象都可以 插入到矢量中,好吧。
是的,没错。
现在,让我说我有两个简单的 称为B和C的类都是派生的 来自A;如果我有一个V1的实例, 那么B和C的两个指针都可以 插入到这个向量中,我想 这是对的吗?
是的,没错。
如果是这样,我如何从中导出一个向量 V1确保只有B指针 插入?我正在考虑使用 模板,但在这种情况下我已经 知道班级的基础和 你可以使用任何东西,对吗?
为什么不使用
std::vector<B*> m_bVector;
对于这种情况?以下是它的工作原理:
B* bInstance = new B();
A* aInstance = new A();
m_bVector.push_back(bInstance);
m_bVector.push_back(aInstance); //< compiler error
也许你有充分的理由从vector继承,但我现在没有看到它......如果你需要增加功能,那么让V1包装std :: vector可能会更好,即:
class V1
{
private:
std::vector<A*> m_aVec;
public:
// use AVec
}
答案 1 :(得分:2)
作为一般经验法则,您不应该从STL容器派生。为什么不在vector<A*>
内使用class V1
成员?
答案 2 :(得分:1)
如果要在向量中存储B指针,最好的解决方案是从
派生std::vector<B*>
或者,如果你想让你的班级也使用A指针,可以制作一个模板
template<typename T>
class MyVec : public std::vector<T> {
};
MyVec<A*> va; // stores A* and B*
MyVec<B*> vb; // stores B* only
答案 3 :(得分:0)
如果是这样,我如何从V1导出一个向量以确保只插入B指针?
撇开你不应该从STL容器继承(对于可能不明显的number of reasons),答案是你没有。不管怎样,不是真的。
您可以进行只能插入B*
的运行时断言:
if(!dynamic_cast<B*>(item))
return false;
但这依赖于C ++的RTTI支持,通常非常慢。您可以使用某种“自己动手”的RTTI接口(即,一个返回标识该类的枚举的函数),或者可能是Boost的static assert测试{{1对象。
我的偏好是:
typeof
然后使用template<typename T>
class V1 {
private:
std::vector<T*> _vec;
// ...
};
的类型进行实例化,这对您的用例有意义。
但是如果你的案例有时会依赖于所有T
,有时候所有B*
,那么我会认为你的设计很糟糕,应该重新思考。