Преимущества typedef перед производным классом? - PullRequest
7 голосов
/ 02 сентября 2011

Проще говоря, каковы (или есть) различия между тем, как сказать

class MyClassList : list<MyClass> { };

против

typedef list<MyClass> MyClassList;

Единственное преимущество, которое я могу себе представить (и его чтоприводит меня к этому вопросу), что с производным классом я могу теперь легко объявить MyClassList как

class MyClassList;

без ошибки компилятора вместо

class MyClass;
typedef list<MyClass> MyClassList;

Я не могу думать окакие-то различия, но это заставило меня задуматься, есть ли случаи, когда можно использовать typedef, чего не может простой производный класс?

Или, другими словами, есть ли причина, по которой я не долженизменить весь мой список typedef <...> SomeClassList;к простому производному классу, чтобы я мог легко объявить их вперед?

Ответы [ 5 ]

9 голосов
/ 02 сентября 2011

В C ++ НЕ рекомендуется выводить из контейнера STL, поэтому не делайте этого.

A typedef просто создает псевдоним для существующего типа, поэтому typedef std::list<MyClass> MyClassList; создает «новый тип», который называется MyClassList, который теперь можно использовать следующим образом:

MyClassList lst;

Смена ваших typedef на производный класс - плохая идея. Не делай этого.

5 голосов
/ 02 сентября 2011

typedef предназначен именно для этой цели - для псевдонимов имен типов.Он очень идиоматичен и не смущает никого, кто знаком с C ++.

Но для решения вопроса, почему наследование может быть плохой идеей.

std::list не имеет виртуального деструктора.Значение MyClassList не приведет к вызову деструктора при удалении через базовый класс.Так что это, как правило, осуждается.В вашем случае вы не собираетесь помещать какие-либо члены в MyClassList, поэтому это становится спорным вопросом , пока следующий программист не увидит наследование как приглашение добавить новых членов / переопределить функции и т. Д. .Они могут не понимать, что деструктор std::list не является виртуальным, и не понимать, что в некоторых случаях деструктор MyClassList не будет вызван.

3 голосов
/ 02 сентября 2011

Что ж, typedef может делать только то, что предполагает его имя, в то время как производный класс может быть полноценным преобразованием своей базы (баз).Так что, хотя может не быть большой разницы, если вы ограничиваете себя «просто» производным (и не добавляете какие-либо члены, не переопределяете что-либо и т. Д.) В том, что касается компилятора, может быть большая разница в том, что касается человекачитатели кода обеспокоены.

Кто-то может задаться вопросом «почему это производный класс, когда typedef будет достаточно»?Большинство людей предполагает, что должна быть причина, чтобы вы могли усложнить жизнь будущим разработчикам кода.A typedef, с другой стороны, является очень специфическим инструментом и не вызывает вопросов.

И пока мы занимаемся вопросами обслуживания, не забывайте, что, как и большинство вещей в C ++, это "ничто не пойдет не так, если мы дисциплинированы и не пересекаем эту черту »- это открытое приглашение к катастрофе.Поскольку компилятор не остановит вас, кто-нибудь когда-нибудь пересечет черту.

0 голосов
/ 02 сентября 2011

Typedef является псевдонимом, а класс - новым типом. В первом случае компилятор должен просто заменить MyClassList списком . Во втором случае MyClassList включает генерацию конструктора по умолчанию, оператора присваивания конструктора копирования, деструктора и - где используется c ++ 11 - даже перемещение конструктора и перемещение. В случаях по умолчанию, поскольку MyClassList не имеет дополнительных функций, оптимизация, скорее всего, уничтожит их.

Примечание: я обнаружил, что аргумент "создание классов с не виртуальным деструктором не рекомендуется" является слабым аргументом. Разработчик C ++ должен знать, что деривация не обязательно подразумевает полиморфизм. Класс, который не удаляется через указатель на его базу, не нуждается в виртуальном деструкторе, как класс, метод которого не предназначен для «вызова» через указатель на базу, не требует, чтобы этот метод был виртуальным. Проще говоря, если деструктор не является виртуальным, не рассматривайте этот тип как «полиморфный» при удалении. В этом смысле деструктор не отличается от других виртуальных или не виртуальных методов. Если этот аргумент нужно считать сильным, то все классы, у которых нет «всех виртуальных» методов, не должны быть получены!

0 голосов
/ 02 сентября 2011

Ряд вещей были упомянуты.Важная вещь, однако:

Производные от типа не наследуют все конструкторы.

Если есть несколько конструкторов, отличных от заданных по умолчанию, они не будут у вас при наследовании (вам придется перенаправить их в базовый конструктор).вопрос.

Теперь typedefs не генерируют уникальные typeid.Если вы хотите этого и не имеете накладных расходов или других недостатков наследования, посмотрите на boost: он имеет сильный макрос typedef, который генерирует уникальный typeid:

http://www.boost.org/doc/libs/1_37_0/boost/strong_typedef.hpp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...