Existe algún riesgo real de derivar de los contenedores C ++ STL?

La afirmación de que es un error utilizar un contenedor C ++ estándar como clase base me sorprende.

Si no es abuso del lenguaje declarar ...

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

... entonces, ¿cuál es exactamente el peligro al declarar ...

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

Las ventajas positivas para B incluyen:

Permite la sobrecarga de funciones porque f (Tasas y) yf (Cargos y) son firmas distintas Permite que otras plantillas se especialicen, porque X <Rates> y X <Charges> son tipos distintosa declaración de @Forward es trivialDebugger probablemente le dice si el objeto es una Tarifa o un CargoSi, a medida que pasa el tiempo, las Tarifas y los Cargos desarrollan personalidades, un Singleton para las Tarifas, un formato de salida para los Cargos, hay un alcance obvio para implementar esa funcionalidad.

Las ventajas positivas de A incluyen:

No tiene que proporcionar implementaciones triviales de constructores, etc. El compilador pre-estándar de quince años que es lo único que compilará tu legado no se ahoga Debido a que las especializaciones son imposibles, la plantilla X <Tasas> y la plantilla X <Cargos> usarán el mismo código, por lo que no hay hinchazón sin sentido.

os enfoques de @Both son superiores al uso de un contenedor sin procesar, porque si la implementación cambia de vector <double> a vector <float>, solo hay un lugar para cambiar con B ytal ve solo un lugar para cambiar con A (podría ser más, porque alguien puede haber puesto declaraciones typedef idénticas en varios lugares).

Mi objetivo es que esta sea una pregunta específica y que responda, no una discusión de una práctica mejor o peor. Muestre lo peor que puede suceder como consecuencia de derivar de un contenedor estándar, que se habría evitado utilizando un typedef en su lugar.

Editar

Sin preguntas, agregar un destructor a la clase Tasas o Cargos de clase sería un riesgo, porque std :: vector no declara su destructor como virtual. No hay destructor en el ejemplo, y no hay necesidad de uno. La destrucción de un objeto Tasas o Cargos invocará al destructor de la clase base. Tampoco hay necesidad de polimorfismo aquí. El desafío es mostrar que algo malo sucede como consecuencia del uso de derivación en lugar de typedef.

Editar

Considere este caso de uso:

#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;
}

¿Hay algún error posible que incluso un usuario arbitrariamente desafortunado pueda introducir en el ??? sección que dará lugar a un problema con los cargos (la clase derivada), pero no con las tarifas (el typedef)?

En la implementación de Microsoft, el vector <T> se implementa a través de la herencia. el vector <T, A> se deriva públicamente de _Vector_Val <T, A> ¿Debería preferirse la contención?

Respuestas a la pregunta(16)

Su respuesta a la pregunta