为了账号安全,请及时绑定邮箱和手机立即绑定

从C ++ STL容器中获取是否存在任何真正的风险?

从C ++ STL容器中获取是否存在任何真正的风险?

C++
慕的地8271018 2019-08-19 17:29:26
从C ++ STL容器中获取是否存在任何真正的风险?声称使用标准C ++容器作为基类是错误的说法让我感到惊讶。如果没有滥用语言来宣布......// Example Atypedef std::vector<double> Rates;typedef std::vector<double> Charges;......那么确切地说,宣告的危险是什么......// Example Bclass Rates : public std::vector<double> {     // ...} ;class Charges: public std::vector<double> {     // ...} ;B的积极优势包括:启用函数重载,因为f(Rates&)和f(Charges&)是不同的签名允许其他模板专用,因为X <Rates>和X <Charges>是不同的类型前瞻性声明是微不足道的调试器可能会告诉您对象是费率还是费用如果随着时间的推移,费率和费用会产生个性 - 一个单一的费率,费用的输出格式 - 这个功能有明显的实施范围。A的积极优势包括:不必提供构造函数等的简单实现十五年前的预标准编译器是唯一能够编译遗产的编译器由于专业化是不可能的,模板X <费率>和模板X <费用>将使用相同的代码,因此没有毫无意义的膨胀。这两种方法都优于使用原始容器,因为如果实现从vector <double>更改为vector <float>,那么只有一个地方可以用B更改,也许只有一个地方可以用A更改(可能更多,因为有人可能在多个地方放置了相同的typedef语句。我的目标是这是一个具体的,可回答的问题,而不是对更好或更差实践的讨论。显示由于从标准容器派生而可能发生的最糟糕的事情,这可以通过使用typedef来防止。编辑:毫无疑问,向类Rate或类Charges添加析构函数会有风险,因为std :: vector不会将其析构函数声明为虚拟。示例中没有析构函数,也不需要析构函数。销毁Rates或Charges对象将调用基类析构函数。这里也不需要多态性。挑战在于使用派生而不是使用typedef来表明发生了一些不好的事情。编辑:考虑这个用例:#include <vector>#include <iostream>void kill_it(std::vector<double> *victim) {     // user code, knows nothing of Rates or Charges    // invokes non-virtual ~std::vector<double>(), then frees the     // memory allocated at address victim    delete victim ; }typedef std::vector<double> Rates;class Charges: public std::vector<double> { };int main(int, char **) {  std::vector<double> *p1, *p2;  p1 = new Rates;  p2 = new Charges;  // ???    kill_it(p2);  kill_it(p1);  return 0;}是否有任何可能的错误,甚至一个任意不幸的用户可以在??? 哪个部分会导致Charges(派生类)出现问题,但不会导致Rate(typedef)?在Microsoft实现中,vector <T>本身是通过继承实现的。vector <T,A>是公开派生自_Vector_Val <T,A>应该包含首选吗?
查看完整描述

3 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

标准容器没有虚拟析构函数,因此您无法以多态方式处理它们。如果你不这样做,并且每个使用你代码的人都不这样做,那本身就不是“错误的”。但是,为了清晰起见,最好还是使用合成。


查看完整回答
反对 回复 2019-08-19
?
aluckdog

TA贡献1847条经验 获得超7个赞

因为你需要一个虚拟析构函数而std容器没有它。std容器不能用作基类。

有关更多信息,请阅读文章“为什么我们不应该从STL类继承一个类?”

准则 

基类必须具有:

  • 公共虚拟析构函数

  • 或受保护的非虚拟析构函数


查看完整回答
反对 回复 2019-08-19
?
12345678_0001

TA贡献1802条经验 获得超5个赞

在我看来,一个强有力的反驳是你正在强加一个界面你的类型的实现。当您发现向量内存分配策略不符合您的需求时会发生什么?你会从中衍生出来std:deque吗?那些已经使用你的类的128K代码行怎么样?每个人都需要重新编译一切吗?它会编译吗?


查看完整回答
反对 回复 2019-08-19
  • 3 回答
  • 0 关注
  • 441 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信