Почему я не могу объявить друга через typedef?

StackOverflow https://stackoverflow.com/questions/392120

  •  23-08-2019
  •  | 
  •  

Вопрос

Кто-нибудь знает, почему определения типов имен классов не работают как имена классов для объявления друга?

class A
{
public:
};

class B : public A
{
public:
   typedef A SUPERCLASS;
};

typedef A X;

class C
{
public:
   friend class A;             // OK
   friend class X;             // fails
   friend class B::SUPERCLASS; // fails
};
Это было полезно?

Решение

В настоящее время это невозможно.Я пока не знаю причину (просто ищу, потому что мне это интересно).Обновлять:причину можно найти в первом предложении о поддержке имен typedef в качестве друзей: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1520.pdf .Причина в том, что стандарт поддерживает только уточненные спецификаторы типов.Легко разрешить только их и сказать, что если объект, объявленный как друг, еще не объявлен, он станет членом окружающего пространства имен.Но это означает, что если вы хотите использовать параметр шаблона, вам придется сделать (например, тогда потребуется класс)

friend class T;

Но это принесло дополнительные проблемы, и было решено, что выгода от этого не стоит.Теперь в документе предлагается разрешить задавать дополнительные спецификаторы типов (чтобы затем можно было использовать параметры шаблона и имена typedef).

Следующая версия C++ (начиная с 2010 г.) сможет это сделать.

См. это обновленное предложение по стандарту: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf .Это не позволит использовать только имена typedef, но и параметры шаблона в качестве типа, объявленного как дружественный.

Другие советы

AFAIK, в C++ typedef не создает полноценные синонимы при использовании в сочетании с классами.Другими словами, это не макрос.

Среди ограничений является то, что синоним не может появляться после префикса класса или структуры или использоваться в качестве имени деструктора или конструктора.Вы также не можете подклассифицировать синоним.Могу поспорить, что это также означает, что вы не можете добавить его в друзья.

Я попробовал в VC++ 8.0 код:

...
class C
{
public:
  friend class A;       
  friend X;             
  friend B::SUPERCLASS; 
};
...

Компилируется без ошибок.

Я не знаю, специфично ли это для MS или нет.

Typedef определяет тип.Дружественные объявления объявляют дружественные классы или функции (по существу, области видимости), которые затем имеют «доступ» к закрытой области объявляющего класса...

Примитивы, т.е.Поплавок или int* не определяйте область применения с кодом и т. Д., Они не «используют» класс в любом случае.

Не забывайте, что вы также можете «упаковать» соглашения о вызовах, атрибуты выравнивания и другие вещи, специфичные для компилятора, в typedef, т.е.несколько ТИПОВ векторов, реализованных одним и тем же классом, но с разными атрибутами выравнивания.=> Тип не является классом, и наоборот.

ИМХО, объявление определения типа друга может быть полезным, но когда «определения типов класса» из любого места могут быть установлены как друзья, дружба может стать крайне непонятной и, следовательно, подверженной ошибкам, особенно там, где шаблоны используются чрезмерно.

Аннулирование одного определения типа может испортить весь проект из-за широко распространенных зависимостей.Друзья шаблонов и определения типов шаблонов 0x полезны, но не ослабляйте правила объявления друзей.

Я не знаю ни одного предложения относительно определения типов друзей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top