需要一个从向量派生的向量
Posted
技术标签:
【中文标题】需要一个从向量派生的向量【英文标题】:Need a vector that derives from a vector 【发布时间】:2009-11-03 18:20:40 【问题描述】:考虑这个简单的代码:
class A
;
class V1: vector<A *>
// my nice functions
;
如果我有一个 V1 的实例,那么任何从 A 派生的对象都可以插入到向量中,在这里可以。
现在,假设我有两个名为 B 和 C 的简单类都派生自 A; 如果我有一个 V1 的实例,那么 B 和 C 的指针都可以插入到这个向量中,我想这是正确的吗?
如果是这样,我如何从 V1 派生一个向量以确保只插入 B 指针? 我正在考虑使用模板,但在这种情况下,我已经知道类的基础,并且在模板中你可以使用任何东西,对吧?
不知道我是否清楚,我的英语没有帮助...... 我是否必须重写 push_back 和其他函数来检查模板参数是否从 A 派生?
请不要谈论我正在使用的提升或语法等......我真的只是想了解这个的概念......我还不清楚。我对此有一些答案,但我想它们涉及太多演员来检查东西,我来这里是想知道是否有更好的答案......
谢谢! 乔纳森
ps:你们能回答我放的cmets吗?有时我在这里问一些东西,然后最好的回答者来了,然后就不回来了:(。或者我应该问另一个问题而不是评论提问?
【问题讨论】:
明确一点,你B派生自A,但你不想在V1中存储指向B对象的指针,只存储指向A对象的指针? 对不起...我有一个名为 A 的抽象类,然后我将有几个从 A 派生的类,例如 B 和 C。然后会有一个向量,每个(或大多数)派生自A. 像vector、vector从您的示例中不清楚是否需要继承。您可能还没有意识到它很危险,因为 std::vector 没有虚拟析构函数。这意味着在删除指向基类的指针时不会调用 V1 的析构函数,并且您最终可能会泄漏内存/资源。请参阅here 了解更多信息。
class A
;
class V1: vector<A *>
// my nice functions
;
如果我有一个 V1 的实例,那么任何从 A 派生的对象都可以是 插入向量中,这里ok。
是的,正确。
现在,假设我有两个简单的 名为 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
【讨论】:
我有几个函数在逻辑上不能在同一个向量中包含不同的对象,即使它们派生自同一个类。但它们必须从 A 派生,所以我可以使用 A 成员和函数... 阅读您的帖子并思考您所写的内容...是的,我可以将矢量包装在课堂内,如果需要,使用外部模板 “它们必须从 A 派生,以便我可以使用 A 成员和函数”。我建议重新设计:将 V1 编写为模板类而不是普通类。使其成为“容器适配器”,例如std::stack
,这意味着它有一个向量(或其他容器)作为成员,并且具有您需要的自己的功能。然后你可以创建一个V1<A*, vector>
、V1<B*, vector>
,或者其他的。
这意味着 V1 的析构函数不完全准确。只有通过指向基类的指针销毁析构函数时,才会调用析构函数。【参考方案2】:
一般来说,您不应该从 STL 容器派生。为什么不在class V1
中使用vector<A*>
成员?
【讨论】:
好的,即使是这样,我怎样才能确保模板只有B指针(在上面的情况下)?typedef vector<B*> VectorOfBs;
?
但是我已经有一个类,它的函数使用 A 成员和例程的向量,所以 vector 需要这些函数【参考方案3】:
如果你想在你的向量中存储 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
【讨论】:
是的,但在模板情况下,我如何确保 T 派生自 A?在 C# 中,它将是“where”关键字。比如:类 S: List如果是这样,我如何从 V1 派生一个向量以确保只插入 B 指针?
撇开您不应该从 STL 容器继承(对于 number of reasons 这可能并不明显),答案是您不应该继承。反正也不是。
您可以在运行时断言只能插入B*
:
if(!dynamic_cast<B*>(item))
return false;
但这依赖于 C++ 的 RTTI 支持,通常非常慢。您可以改为使用某种“滚动您自己的”RTTI 接口(即,一个返回标识类的枚举的函数),或者可能是 Boost 的 static assert 测试 typeof
对象.
我的偏好是这样的:
template<typename T>
class V1
private:
std::vector<T*> _vec;
// ...
;
然后使用对您的用例有意义的T
类型进行实例化。
但是,如果您的案例依赖于有时全是 B*
s,有时全是 A*
s,那么我会认为您的设计很糟糕,应该重新考虑。
【讨论】:
大声笑 =p。这不是我的情况,呵呵,向量永远不会有混合类型,但我将拥有使用该实例基础的功能,例如加载 xml 数据等 那么我认为你的设计是错误的,你使用继承不当。以上是关于需要一个从向量派生的向量的主要内容,如果未能解决你的问题,请参考以下文章