Почему вводится имя класса?


147

Недавно я увидел странную особенность C ++: введенное имя класса .

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

Но я не могу понять, почему эта функция необходима. Есть ли практика, которая требует этой функции?

И я слышал, что эта функция не существовала в старом C ++. Тогда когда это было введено? C ++ 03? C ++ 11?


Дружище, можешь посмотреть по скайпу? Я не могу связаться с вами
Иринель Иован

Ответы:


162

Внедренное имя класса означает, что 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; };


2
Меня часто спрашивают об этом, но я никогда не смог создать простой пример, указывающий на проблему. Так что +1 Для примера.
Дхейн

1
Это хорошо видно, если вы запустите clang ++ your_program.cpp -Xclang -ast-dump и увидите свой класс, а затем внедренный дочерний узел класса.
xaxxon
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.