объявление класса друга и директива using
-
21-12-2019 - |
Вопрос
Правильно ли сформулирован следующий пример?
namespace N {
class A;
}
using namespace N;
class B {
int i;
friend class A;
};
namespace N {
class A {
B m;
int get() { return m.i; }
};
}
Этот пример успешно скомпилировался с Clang 3.5, но не скомпилировался с g++ 4.8.1 со следующим:
main.cpp: In member function ‘int N::A::get()’:
main.cpp:7:9: error: ‘int B::i’ is private
int i;
^
main.cpp:14:30: error: within this context
int get() { return m.i; }
^
Стандарт C++11 §7.3.1.2 p3 гласит:
Если имя в
friend
заявление не является ни квалифицированным, ни идентификатор шаблона и объявление является функцией или разработанный спецификатор типа, поиск для определения того, была ли сущность объявлена ранее, не должен учитывать какие-либо области за пределами самого внутреннего охватывающего пространства имен.
Например, class A
не является членом самое внутреннее пространство имен (т.е.глобальное пространство имен), но class A
вводится с помощью директивы using в глобальное пространство имен.
Решение
При использовании пространства имен N имя N::A помещается в глобальное пространство имен, но не объявляется, что A находится в глобальном пространстве имен.Следовательно, дополнительный A в глобальном пространстве имен является другом B.лязг - это неправильно.
Другие советы
Делать N::A
без квалификации а friend
из B
ты бы использовал
friend A;
скорее, чем
friend class A;
При использовании подробного спецификатора типа, т.е. class A
, и именно в этой конкретной форме он вводит имя класса (см. 3.4.4 [basic.lookup.elab] параграф 2).