2012-06-07 7 views
6

Я два вопроса об этом коде ниже:друг функции класса внутри пространства имен

namespace A { class window; } 

void f(A::window); 

namespace A 
{ 
    class window 
    { 
    private: 
     int a; 
     friend void ::f(window); 
    }; 
} 

void f(A::window rhs) 
{ 
    std::cout << rhs.a << std::endl; 
} 

1) Почему я должен квалифицироваться функции члена е внутри оконного класса должен быть глобальным, делая :: f (окно)?

2) почему в этом конкретном случае необходимо предусмотреть функцию f (A :: window), тогда как когда класс не определен внутри пространства имен, нормально объявлять функцию после того, как функция объявлена друг.

+0

Вот краткое объяснение того, какие дружественные классы http://www.cplusplus.com/doc/tutorial/inheritance/ –

+0

@ Жаль, но это не мой вопрос – AlexDan

+1

@ Спасибо, пожалуйста, не связывайтесь cplusplus.com - http://programmers.stackexchange.com/q/88241/36523 – Griwes

ответ

4

Когда вы объявляете f() в качестве друга, это фактически делается в охватывающем пространстве имен содержащего класса (A в этом случае), если декларация пересылки еще не существует.

Так это ...

namespace A 
{ 
    class window 
    { 
    private: 
     friend void ::f(window); 
    }; 
} 

по существу становится это ...

namespace A 
{ 
    class window; 
    void f(window); 

    class window 
    { 
    private: 
     friend void f(window); 
    }; 
} 

Edit: Вот фрагмент из C++ стандарта, что explicltly говорит об этом сценарии:

Стандарт 7.3.1.2/3:

Каждое имя, объявленное в пространстве имен, является членом этого пространства имен. Если декларация друга в нелокальном классе сначала объявляет класс или функцию, класс или функция друга является членом самого внутреннего охватывающего пространства имен. Имя друга не найдено по неквалифицированному поиску (3.4.1) или по квалифицированному поиску (3.4.3), пока в этой области пространства имен не будет представлено соответствующее объявление (до или после определения класса, дающего дружбу).

+0

Итак, в примере выше, f (window) обрабатывается членом пространства имен A? –

+0

@ VishnuPedireddi Да. –

+0

Что делать, если f (окно) определено в пространстве имен собственного пространства имен имен B? Будет ли f (окно) принадлежать пространству имен A и пространству имен B? –

3

Что касается 1), то ваша функция не находится в пространстве имен, поэтому вы должны использовать ::, чтобы сообщить компилятору выполнить поиск за пределами пространства имен.

В противном случае он будет искать функцию внутри пространства имен (вот почему они существуют). Поиск Koenig здесь не применяется, поскольку класс окна находится внутри пространства имен.

не слишком уверен в отношении 2) хотя, но я уверен, что это связано с 1).

1

1) потому что функция f объявлена ​​и определена за пределами текущего пространства имен. Если вы переместили определение своего класса в то же пространство имен, что и функция, будь то глобальная или в противном случае вам не нужно.

2) вам всегда нужно объявить функцию до ее ссылки. Ваш класс ссылается на функцию с выражением друга.

+0

Что вы подразумеваете под рефренсами? как насчет того, когда класс не внутри какого-либо namaespace не является тем же случаем здесь? – AlexDan

+0

Должна быть доступна функция. Если класс находится в том же пространстве имен, что и определение функции, оно может найти его, но порядок объявления. Вот почему определение вашей функции должно появиться после объявления класса, поскольку оно использует элемент из этого класса. – AJG85

+0

Что касается (2), см. Ответ CaptainObvlious - есть тонко. AlexDan здесь не совсем корректно. Иногда объявление друга не требует ссылки на функцию, объявленную ранее - вместо этого сама декларация друга считается официальным объявлением функции, а функция может быть определена позже. См. Ответ CaptainObvlious. –

Смежные вопросы