gpt4 book ai didi

c++ - 从 C++ STL 容器派生是否有任何真正的风险?

转载 作者:IT老高 更新时间:2023-10-28 12:42:46 27 4
gpt4 key购买 nike

声称使用标准 C++ 容器作为基类是错误的,这让我感到惊讶。

如果不是滥用语言来声明...

// Example A
typedef std::vector<double> Rates;
typedef std::vector<double> Charges;

...那么,确切地说,声明...的危险是什么

// Example B
class Rates : public std::vector<double> {
// ...
} ;
class Charges: public std::vector<double> {
// ...
} ;

对 B 的积极优势包括:

  • 启用函数重载,因为 f(Rates &) 和 f(Charges &) 是不同的签名
  • 使其他模板能够被专门化,因为 X 和 X 是不同的类型
  • 前向声明很简单
  • 调试器可能会告诉您对象是 Rates 还是 Charges
  • 如果随着时间的推移,Rates 和 Charges 发展出个性(即 Rates 的 Singleton,Charge 的输出格式),那么该功能的实现范围就很明显了。

A 的积极优势包括:

  • 不必提供构造函数等的琐碎实现
  • 只有 15 年历史的准标准编译器,它是唯一可以编译您的遗留系统的东西,不会窒息
  • 由于无法进行特化,模板 X 和模板 X 将使用相同的代码,因此不会出现无意义的膨胀。

这两种方法都优于使用原始容器,因为如果实现从 vector 更改为 vector ,则只有一个地方可以用 B 更改, 可能只有一个地方可以更改用 A 改变(可能更多,因为有人可能在多个地方放置了相同的 typedef 语句)。

我的目标是这是一个具体的、可回答的问题,而不是讨论更好或更坏的做法。显示由于从标准容器派生而可能发生的最糟糕的事情,而这可以通过使用 typedef 来避免。

编辑:

毫无疑问,向 Rates 类或 Charges 类添加析构函数是有风险的,因为 std::vector 没有将其析构函数声明为虚拟。示例中没有析构函数,也不需要析构函数。销毁 Rates 或 Charges 对象将调用基类析构函数。这里也不需要多态性。挑战在于展示由于使用派生而不是类型定义而发生的不良事件。

编辑:

考虑这个用例:

#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)出现问题?

在 Microsoft 实现中,vector 本身是通过继承实现的。 vector 是公开派生自 _Vector_Val 是否应该首选包含?

最佳答案

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

关于c++ - 从 C++ STL 容器派生是否有任何真正的风险?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/922248/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com