2012-06-07 6 views
9

Im Versuch, eine Klasse friend-Funktion außerhalb des Namespace wie folgt zu definieren:Klasse friend-Funktion in einem Namespace

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

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

Im einen Fehler immer gesagt, dass es eindeutig ist. und es gibt zwei Kandidaten void A::f(A::window); und void f(A::window). Also meine Frage ist:

1) Wie man die globale Funktion void f(A::window rhs) einen Freund der Klasse A :: window.

EDIT: (nach den Antworten zu lesen)

2), warum muss ich die Member-Funktion f innerhalb Fensterklasse qualifizieren global sein von ::f(window) tun?

3) Warum muss ich die Funktion f (A :: window) in diesem speziellen Fall vordefinieren, während wenn die Klasse nicht innerhalb eines Namespaces definiert ist, ist OKey für die deklarierte Funktion, nachdem die Funktion deklariert wurde ein Freund.

Antwort

15

sowie das Hinzufügen eines :: Sie es erklären weiterleiten müssen, z.B .:

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; 
} 

Beachten Sie, dass für diese Forward-Deklaration Sie auch die Klasse deklarieren weiterleiten müssen an die Arbeit!

+0

so der :: Präfix für den Zugriff auf globalen Namensraum ist derjenige, der erforderlich vordefinierte Funktion void f (A :: window); ist das richtig. Danke im Voraus. – AlexDan

+0

Ja, das funktioniert, wenn die Funktion void zurückgibt. Aber was, wenn es eine Instanz einer Klasse zurückgibt, sagen wir B? Dann stößt der Compiler auf "Freund B :: f()", weil er denkt, dass wir "B :: f()" meinen (d. H. Eine Funktion der Klasse B im Gegensatz zu einer globalen Funktion). Irgendeine Lösung dafür? –

+0

Ich sehe nicht, wie Sie mit einem Namenskonflikt so legal enden können - können Sie es auf etwas wie ideone zeigen? – Flexo

4

Dies sollte es tun: Sie müssen erklärt vorwärts im globalen Namensraum (und nicht die Datei statisch) klar f zu machen:

#include <string> 
#include <iostream> 

using namespace std; 

////// forward declare magic: 

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

////// 

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

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

int main() 
{ 
}