Вопрос

Правильно ли сформулирован следующий пример?

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).

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