使用标准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
  • 如果随着时间的流逝,费率和收费发展出个性-费率单例,收费的输出格式-显然可以实现该功能。

  • A的积极优势包括:
  • 不必提供琐碎的构造函数实现等
  • 十五岁的标准编译器是唯一可以编译您的遗留内容的工具,不会令
  • 窒息
  • 由于无法进行特化,因此模板X 和模板X 将使用相同的代码,因此不会毫无意义。

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

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

    编辑:

    毫无疑问,将析构函数添加到Rates或Charge类中是有风险的,因为std::vector不会将其析构函数声明为virtual。该示例中没有析构函数,也不需要一个析构函数。销毁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(派生类)出现问题,而不会导致Rates(typedef)出现问题?

    在Microsoft实现中,vector 本身是通过继承实现的。 vector 是从_Vector_Val 公开派生的,应该首选围堵吗?

    最佳答案

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

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

    10-11 23:03
    查看更多