Is there any real risk to deriving from the C++ STL containers?(从 C++ STL 容器派生是否有任何真正的风险?)
问题描述
声称使用标准 C++ 容器作为基类是错误的,这让我感到惊讶.
The claim that it is a mistake ever to use a standard C++ container as a base class surprises me.
如果声明不是滥用语言...
If it is no abuse of the language to declare ...
// Example A
typedef std::vector<double> Rates;
typedef std::vector<double> Charges;
... 那么,声明...的危害究竟是什么
... then what, exactly, is the hazard in declaring ...
// Example B
class Rates : public std::vector<double> {
// ...
} ;
class Charges: public std::vector<double> {
// ...
} ;
B 的积极优势包括:
- 启用函数重载,因为 f(Rates &) 和 f(Charges &) 是不同的签名
- 使其他模板能够被专门化,因为 X
X<费用>是不同的类型 - 前向声明很简单
- 调试器可能会告诉您对象是 Rates 还是 Charges
- 如果随着时间的推移,费率和费用会形成个性——费率的单例,费用的输出格式—该功能有明显的实现空间.
A 的积极优势包括:
- 不必提供构造函数等的琐碎实现
- 十五年前的标准前编译器是唯一可以编译您的遗留系统的编译器,它不会阻塞
- 由于不可能进行专业化,因此模板 X
和模板X<Charges>将使用相同的代码,因此不会出现毫无意义的膨胀.
这两种方法都优于使用原始容器,因为如果实现从 vector
Both approaches are superior to using a raw container, because if the implementation changes from vector<double> to vector<float>, there's only one place to change with B and maybe only one place to change with A (it could be more, because someone may have put identical typedef statements in multiple places).
我的目标是这是一个具体的、可回答的问题,而不是讨论更好或更坏的实践.显示由于从标准容器派生而可能发生的最糟糕的事情,而使用 typedef 可以防止这种情况发生.
My aim is that this be a specific, answerable question, not a discussion of better or worse practice. Show the worst thing that can happen as a consequence of deriving from a standard container, that would have been prevented by using a typedef instead.
毫无疑问,将析构函数添加到类 Rates 或类 Charges 将是一种风险,因为 std::vector 没有将其析构函数声明为虚拟的.示例中没有析构函数,也不需要一个.销毁 Rates 或 Charges 对象将调用基类析构函数.这里也不需要多态性.挑战在于展示由于使用派生而不是 typedef 而导致的一些不好的事情发生.
Without question, adding a destructor to class Rates or class Charges would be a risk, because std::vector does not declare its destructor as virtual. There is no destructor in the example, and no need for one. Destroying a Rates or Charges object will invoke the base class destructor. There is no need for polymorphism here, either. The challenge is to show something bad happening as a consequence of using derivation instead of a 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(派生类)出现问题,但不会导致 Rates(typedef)出现问题?
Is there any possible error that even an arbitrarily hapless user could introduce in the ??? section which will result in a problem with Charges (the derived class), but not with Rates (the typedef)?
在 Microsoft 实现中,vector
In the Microsoft implementation, vector<T> is itself implemented via inheritance. vector<T,A> is a publicly derived from _Vector_Val<T,A> Should containment be preferred?
推荐答案
标准容器没有虚拟析构函数,因此你不能多态地处理它们.如果您不这样做,并且使用您的代码的每个人都没有这样做,那么这本身就不是错误".但是,为了清楚起见,您最好还是使用合成.
The standard containers do not have virtual destructors, thus you cannot handle them polymorphically. If you will not, and everyone who uses your code doesn't, it's not "wrong", per se. However, you are better off using composition anyway, for clarity.
这篇关于从 C++ STL 容器派生是否有任何真正的风险?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从 C++ STL 容器派生是否有任何真正的风险?


基础教程推荐
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 常量变量在标题中不起作用 2021-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09