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

Недавно я увидел странную особенность 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?

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 для изменения между C++98 и C++03, который прояснил это.

Идея внедренного имени класса была представлена ​​в C++98, но терминология была новой для C++03.

C++98 говорит:

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

Второе предложение было изменено DR 147, поэтому C++03 говорит в [class]/2:

Имя класса вставляется в область, в которой оно объявляется сразу после того, как имя класса замечено. Имя класса также вставляется в область действия самого класса; это известно как имя введенного класса.

Даже до C++98 ARM имеет примерно эквивалентную формулировку, которая означает, что имя класса всегда можно использовать в теле класса для ссылки на сам класс:

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

  • Например,

    class link { link* next; };

Другие вопросы по тегам