Меня удивляет утверждение, что это ошибка, когда-либо использующая стандартный контейнер С++ в качестве базового класса.
Если это не злоупотребление языком для объявления...
// 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 (Тарифы) и f (Сборы &) являются различными сигнатурами
- Позволяет специализировать другие шаблоны, потому что X <Rates> и X < Сборы > являются различными типами.
- Переслать декларацию тривиально
- Отладчик, вероятно, говорит вам, является ли объект тарифами или тарифами
- Если со временем тарифы и сборы будут развиваться личностями; синглтон для тарифов, формат вывода для тарифов — существует очевидная возможность для реализации этой функциональности.
Положительные преимущества для A включают:
- Не нужно предоставлять тривиальные реализации конструкторов и т.д.
- Пятнадцатилетний предварительный стандартный компилятор, что единственное, что скомпилирует ваше наследие, не задушит
- Поскольку специализации невозможны, шаблон X < Цены > и шаблон X < Сборы > будет использовать тот же код, поэтому бессмысленного раздувания.
Оба подхода превосходят использование необработанного контейнера, потому что если реализация изменяется от вектора <double> к вектору <float> , существует только одно место для изменения с B и, возможно, только одно место для изменения с A (это может быть больше, потому что кто-то может помещать идентичные инструкции typedef в несколько мест).
Моя цель состоит в том, что это конкретный, ответственный вопрос, а не обсуждение лучшей или худшей практики. Покажите худшее, что может произойти в результате получения стандартного контейнера, которое было бы предотвращено с помощью typedef.
Edit:
Без сомнения, добавление деструктора в класс "Тарифы" или "Сцены класса" было бы риском, потому что std::vector не объявляет его деструктор виртуальным. В примере нет деструктора, и нет необходимости в нем. Уничтожение объекта тарифов или сборов вызовет деструктор базового класса. Здесь нет необходимости в полиморфизме. Задача состоит в том, чтобы показать что-то плохое из-за использования деривации вместо 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;
}
Есть ли какая-либо возможная ошибка, которую мог бы ввести даже произвольно несчастный пользователь в??? раздел, который приведет к проблеме с тарифами (производным классом), но не с тарифами (typedef)?
В реализации Microsoft вектор <T> сам реализуется через наследование. вектор < Т, А > является публично полученным из _Vector_Val < T, A > Должно быть предпочтительным сдерживание?