Каков правильный способ определения типа и указателя того же типа?

Каков правильный способ определения типа и указателя того же типа? Вот что я имею в виду. Должен ли я сделать это:

typedef unsigned int delay;
typedef unsigned int * delayp;

Или я должен сделать это:

typedef unsigned int delay;
typedef delay * delayp;

Или, возможно, мне вообще не следует указывать указатель typedef и просто использовать delay * вместо delayp везде, где я нахожу это необходимым?

Спасибо, Бода Сидо.


person bodacydo    schedule 12.08.2010    source источник


Ответы (6)


Правильный путь - не делать этого. Сокрытие факта, что что-то является указателем, обычно считается плохим стилем.

person Community    schedule 12.08.2010
comment
В яблочко. И называть тип указателя таким образом, что неясно, что это указатель, это зло. - person PeterK; 12.08.2010
comment
«Скрывать тот факт, что что-то является указателем, обычно считают дурным тоном». Говорит кто? - person Sam; 12.08.2010
comment
Я согласен, что скрытие указателей может привести к путанице. Но я был бы в порядке с typedef delay* delay_ptr;, который не скрывает природу указателя. @ Сэм, это зависит от ситуации. В общем, это может привести к путанице, если вы этого не хотите (то есть вы предоставляете непрозрачный тип, как в обработчике...) - person David Rodríguez - dribeas; 12.08.2010
comment
Раньше это было обычной практикой в ​​старых Windows SDK... что не отрицает, что это плохой стиль. - person UncleZeiv; 12.08.2010
comment
О боже, если бы у меня было 5 центов за каждый раз, когда я это видел. И кстати полностью согласен. - person C Johnson; 12.08.2010
comment
@Sam: определение типа указателя приводит к несоответствиям. А именно const delay* и const delayp ( == delay* const) не одного типа. Вы не можете добавить квалификатор const или volatile к указателю/ссылке с заданным типом. Итак, либо вам нужно сгенерировать все возможные варианты... либо просто никогда не указывать тип указателя/ссылки. - person Matthieu M.; 12.08.2010
comment
Определения типов указателей имели немного больше смысла в 16-битные дни, чтобы абстрагироваться от near и far. - person dan04; 18.01.2011

typedef целое без знака задержка, *delayp;

person badgerr    schedule 12.08.2010
comment
Это очень удивительно, потому что я думал, что typedef работает так: typedef (...) new_name. Итак, в случае указателя я подумал, что это typedef (unsigned int *) new_name. Теперь оказывается, что это работает так же, как объявление типов, так что это не typedef (...) new_name, потому что в typedef unsigned int delay, *delayp часть (...) все еще (unsigned int), но * переместилась рядом с delayp. Я на самом деле очень запутался сейчас. - person bodacydo; 12.08.2010
comment
@bodacydo: синтаксис typedef работает так же, как объявление переменных. - person jamesdlin; 12.08.2010

Как правило, вы делаете второй блок, потому что вы повторно используете тип. Например, если delay нужно было стать unsigned long, определение delayp не нужно было бы изменять.

Тем не менее, прятать указатели за typedef обычно очень плохая идея. Это более приемлемо для вещей, которые действуют как указатели, такие как итераторы или интеллектуальные указатели:

typedef std::vector<int> my_container;
typedef my_container::iterator my_iterator;

typedef some_type<blah> my_type;
typedef shared_ptr<my_type> my_shared_ptr;
person GManNickG    schedule 12.08.2010

typedefing необработанные типы указателей бессмысленны (ха!). Он не обеспечивает никакой реальной абстракции (потребители все равно должны понимать, что типы являются указателями, и они должны выяснить, как анализировать любое соглашение об именах, которое вы используете для имени типа, чтобы определить, что такое тип указателя).

Это также плохой тон, потому что если у вас:

typedef T* T_ptr;

Тогда const T* foo и const T_ptr bar это две большие разницы. (foo — это указатель на const T; это обещание не изменять указатель через этот указатель. bar — это указатель, который сам является const; его нельзя изменить, чтобы он указывал на что-то другое.)

Первый случай (указатель на-const) важен: он помогает обеспечить выполнение контрактов функций.

Второй случай гораздо, гораздо менее полезен.

Поэтому, если вы должны были добавить typedef для типа указателя, чтобы быть полезным, вам нужно было бы создать два:

typedef T* T_ptr;
typedef const T* const_T_ptr;

Допустимое исключение в C++, когда у вас есть классы интеллектуальных указателей. В этих случаях ввод boost::shared_ptr<T> может быть достаточно утомительным, поэтому создание для него typedef является разумным удобством.

person jamesdlin    schedule 12.08.2010

В случае int это не должно иметь никакого значения, но в случае агрегатных типов последний подход лучше, потому что в первом случае *delay не эквивалентен delayp, и для их взаимозаменяемого использования потребуется приведение типов.

Но, как отмечают другие, вам лучше уйти только с delay.

person qrdl    schedule 12.08.2010

Your second form

typedef delay * delayp;
is better because if you'll want in the future to change "delay" typedef from int to something else (long, for instance), you can make this change in one place only.

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

person user396672    schedule 12.08.2010