Ответ 1
Введенное имя класса означает, что X
объявлен как член X
, так что поиск по имени внутри X
всегда находит текущий класс, а не другой X
, который может быть объявлен в той же закрывающей области, например
void X() { }
class X {
public:
static X create() { return X(); }
};
Является ли функция create()
созданием временного объекта X
или вызовом функции X
? В области пространства имен он будет вызывать функцию, поэтому цель имени введенного класса состоит в том, чтобы убедиться, что внутри тела X
имя всегда находит сам класс (поскольку поиск имени начинается в собственной области класса перед тем, как искать в охватывающей области).
Это также полезно внутри шаблонов классов, где имя введенного класса можно использовать без списка аргументов шаблона, например. используя просто Foo
вместо полного идентификатора шаблона Foo<blah, blah, blah>
, поэтому легко обратиться к текущему экземпляру. См. DR 176 для изменения между С++ 98 и С++ 03, которые разъяснили это.
Идея введенного имени класса присутствовала в С++ 98, но терминология была новой для С++ 03.
С++ 98 говорит:
Имя класса вставляется в область, в которой объявляется сразу после просмотра имени класса. Имя класса также вставляется в область самого класса.
Второе предложение было изменено DR 147, поэтому С++ 03 говорит в [class]/2:
Имя класса вставляется в область, в которой объявляется сразу после просмотра имени класса. Имя класса также вставляется в область самого класса; это известно как имя введенного класса.
Даже до С++ 98 ARM имеет примерно эквивалентную формулировку, которая означает, что имя класса всегда можно использовать в теле класса для обозначения самого класса:
Имя класса может использоваться как имя класса даже внутри самого списка участников самого спецификатора класса.
- Например,
class link { link* next; };