Меня удивляет утверждение, что когда-либо использовать стандартный контейнер 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 являются различными типами
- Форвардное объявление тривиально
- Отладчик, вероятно, сообщает вам, является ли объект тарифами или сборами
- Если с течением времени ставки и тарифы развивают личность & mdash; синглтон для тарифов, выходной формат для сборов & mdash; есть очевидные возможности для реализации этой функциональности.
Положительные преимущества для A включают:
- Не нужно предоставлять тривиальные реализации конструкторов и т. Д.
- Пятнадцатилетний предстандартный компилятор, единственное, что скомпилирует ваше наследие, не задохнется
- Поскольку специализации невозможны, шаблон X и шаблон X будут использовать один и тот же код, поэтому бессмысленное раздувание.
Оба подхода превосходят использование необработанного контейнера, потому что, если реализация меняется с вектора на вектор , есть только одно место, которое можно изменить с помощью B, и , возможно, , только одно место, чтобы изменить с A (это может быть больше, потому что кто-то мог поместить одинаковые операторы typedef в нескольких местах).
Моя цель - чтобы это был конкретный, отвечающий на вопросы вопрос, а не обсуждение лучшей или худшей практики. Показать наихудшее, что может произойти в результате извлечения из стандартного контейнера, которое можно было бы предотвратить, если бы вместо этого использовался typedef.
Edit:
Без сомнения, добавление деструктора к классу Rates или классу Charges было бы риском, потому что std :: vector не объявляет свой деструктор виртуальным. В примере нет деструктора, и он не нужен. Уничтожение объекта Rates or 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_Val Должно ли быть предпочтительным включение?