Если вы хотите, вы можете себе представить, что С++ генерирует typedef для каждого тега имя, например
typedef class string string;
К сожалению, это не совсем точный. Хотелось бы, чтобы все было так просто, но это не так. С++ не может генерировать такие typedefs для структур, союзов или перечислений без введения несовместимости с C.
Например, предположим, что программа C объявляет как функцию, так и структуру Именованный статус:
int status(); struct status;
Опять же, это может быть плохая практика, но это C. В этой программе статус (по само) относится к функции; структура статус относится к типу.
Если С++ автоматически генерирует typedefs для тегов, тогда, когда вы скомпилировал эту программу как С++, компилятор будет генерировать:
typedef struct status status;
К сожалению, это имя типа конфликт с именем функции и программа не будет компилироваться. Это почему С++ не может просто генерировать typedef для каждого тега.
В С++ теги действуют так же, как typedef имена, за исключением того, что программа может объявить объект, функцию или перечислитель с тем же именем и та же область действия, что и тег. В этом случае имя объекта, функции или имени счетчика скрывает имя тега. Программа может обратитесь к имени тега только с помощью ключевое слово class, struct, union или перечисление (по мере необходимости) перед название тэга. Название типа, состоящее из одно из этих ключевых слов, за которым следует tag - специфицированный тип-спецификатор. Например, статус структуры и перечисление месяц являются спецификаторами специфицированных типов.
Таким образом, программа C, содержащая оба:
int status(); struct status;
ведет себя так же, когда компилируется как С++. Статус имени относится только к функция. Программа может ссылаться на введите только с помощью структура специфицированного типа-спецификатора статус.
Итак, как это сделать, чтобы ошибки ползли в программы? Рассмотрим программу в Листинг 1. Эта программа определяет class foo с конструктором по умолчанию, и оператор преобразования, который преобразует объект foo в char const *. Выражение
p = foo();
в main должен построить объект foo и примените оператор преобразования. последующий оператор вывода
cout << p << '\n';
должен отображать класс foo, но он не делает. Он отображает функцию foo.
Этот удивительный результат происходит потому, что программа включает в себя заголовок lib.h показано в листинг 2. Этот заголовок определяет функцию, также называемую foo. имя функции foo скрывает имя класса foo, поэтому ссылка на foo в main относится к функции, а не к классу. main может относиться к классу только посредством используя специфицированный тип-спецификатор, так как в
p = class foo();
Как избежать такой путаницы во всей программе - добавить после typedef для имени класса Foo:
typedef class foo foo;
непосредственно перед или после класса определение. Этот typedef вызывает конфликт между именем типа foo и имя функции foo (из библиотеки), которые ошибка времени компиляции.
Я не знаю никого, кто на самом деле пишет эти typedefs, как само собой разумеющееся. Это требует много дисциплины. поскольку частота ошибок, таких как один в Листинг 1, вероятно, довольно Маленькие, многие из вас никогда не сталкиваются с Эта проблема. Но если ошибка в вашем программное обеспечение может привести к телесным повреждениям, то вы должны написать typedefs no вопрос, насколько маловероятно ошибка.
Я не могу себе представить, почему кто-нибудь когда-либо хотите скрыть имя класса с помощью функции или имени объекта в том же как класс. Правила сокрытия в C были ошибкой, и они должны не были распространены на классы в С++. Действительно, вы можете исправить ошибка, но требует дополнительных дисциплина программирования и усилия, которые не требуется.