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