Определение типов указателей - PullRequest
4 голосов
/ 05 декабря 2010

Я читал об SO и натолкнулся на следующие вопросы, в которых затрагивается вопрос, почему типы указателей с определением типов плохие.

Непрозрачные структуры C: как их следует объявлять? Const -корректность и неизменяемые выделенные объекты

Мне было интересно, может ли кто-нибудь расширить и объяснить, почему определение типов указателей плохо работает, и, возможно, привести несколько примеров того, где могут возникнуть ошибки.* Кроме того, если тип указателя определения типа действительно нет-нет, то почему Win32 API делает это?в Win32 HANDLE (и эффективно Handle-типы) typedef'd как void *.

Ответы [ 8 ]

11 голосов
/ 05 декабря 2010

Йоханнес уже заметил, что указатели typedef не являются изначально плохими, и я согласен.

Некоторые рекомендации, основанные на моем субъективном мнении о ясности и удобстве обслуживания:

  • Обычно do typedef типы указателей на функции.

    Причина:
    Объявления указателей на функции могут быть очень запутанными и нечитаемыми.

  • Обычно не typedef необработанные указатели объектов, где тип указателя не является абстракцией (например, когда вам просто нужен "указатель на T ").

    Причина 1:
    Более ясно видеть Foo* или Foo const*, чем, скажем, FooPtr.С именем вы должны найти имя, чтобы увидеть, как оно определяется.Возможно, это какой-то умный указатель, возможно, это указатель на const, что угодно;имя заставляет вас без необходимости искать в другом месте.

    Причина 2:
    Некоторых программистов смущает сочетание типов указателей const и typedef '.Например, в коде Microsoft я много раз видел эквивалент FooPtr const, где программист явно думал, что это означает Foo const*.Но это не так, это означает, что Foo* const.

  • Обычно do typedef также необработанный указатель объекта, когда тип указателя является абстракцией, указательтип, который предположительно может быть заменен другим типом в будущем, например, HANDLE.

    Причина: то же самое, что и для использования именованных констант: без надлежащего имени поиск и замена могут изменить вхождения, которые что-то значатиначе и может не изменить вхождения, которые не выражены точно «правильным» способом.

Однако , как и почти во всех видах стиля, аргументы«за» и «против» довольно слабы, и поэтому выбор в конечном итоге сводится к личным предпочтениям, стандартам кодирования, мнениям коллег и т. д.буду выбирать.Но я отклонился от этих руководящих принципов / правил в особых случаях.Как и в случае с хорошим искусством, хороший код создается теми, кто знает правила достаточно хорошо, чтобы знать, когда их нарушать…

Приветствия & hth.,

6 голосов
/ 05 декабря 2010

Объективно указывать типы указателей не так уж плохо. Хорошо написанный код использует его для определения типа указателя на типы функций-обработчиков, и это также характерно для таких вещей, как HANDLER

Это может быть личное мнение, что это плохо, но это определенно не является общепринятым мнением. Я, например, не согласен с этим мнением вообще. Я сам использую эту опцию реже, но все же не думаю, что она «плохая».

2 голосов
/ 05 декабря 2010

Если вы намереваетесь предоставить тип дескриптора в открытом интерфейсе вашей библиотеки, используйте typedef.Не выставляйте это как struct foo*.Является ли дескриптор указателем или нет, это просто деталь реализации ... он всегда будет действовать так, как если бы он был указателем, но зачастую удобнее использовать индекс в некоторой внутренней структуре данных.

1 голос
/ 05 декабря 2010

Путем «определения типа» указателя вы фактически следуете практике C, а не практике C ++. В C для того, чтобы скрыть детали реализации, часто используется typedef, поскольку он допускает некоторую элементарную форму сокрытия данных:

typedef struct somestruct* pointer;

void foo(pointer p);

, если позже изменилось на

typedef struct someotherstruct* pointer; 

void foo(pointer p);

вам не нужно изменять все параметры функции, которые используют указатель, чтобы "структурировать someotherstruct *", вы даже можете имитировать полиморфизм с этим, добавляя новые поля в someotherstruct.

В C ++ есть и другие способы достичь вышеупомянутого лучшего способа.

edit: возможно, скрытие данных - это слишком сильное слово, но оно позволяет вам изменить реализацию указателя, который использует указатель, без нарушения существующего кода (если все сделано правильно)

1 голос
/ 05 декабря 2010

Как в Windows, так и в POSIX есть указатели typedef, но это не значит, что это всегда хорошая практика. В основном это скрывает детали реализации, но это не всегда хорошо.

0 голосов
/ 23 февраля 2012

Иногда вам нужно заранее объявить структурный указатель для объявления функции для компиляции.Вы не можете просто объявить структуру вперед.

typedef struct my_struct * my_struct_ptr;

extern void my_func( my_struct_ptr pointer );

typedef struct _my_struct { int a_field; } my_struct;

(используя st20cc 3.63)

0 голосов
/ 05 декабря 2010

Нет ничего плохого в использовании указателей typedefs, но вы должны иметь в виду, что typedefs не определяют новые типы (как это делают классы), но определяют псевдонимы для существующих типов.Это означает, что если у вас есть два определения типов, которые являются псевдонимами одного типа, вы не можете полагаться на проверку типов в C ++, чтобы предотвратить непреднамеренное их смешивание.

0 голосов
/ 05 декабря 2010

Ну, если неясно, что такое указатель, а что нет, у вас могут быть проблемы с памятью, windows typedefs HANDLE as void *, поскольку они предоставляют методы для получения и очистки дескрипторов. Это неплохо, но если над проектом работает много людей, я бы рекомендовал против него. В основном это проблема ясности.

...