2014-05-08 10 views
11

Ich habe den folgenden Code:Friend-Funktion ist in der Klasse nicht sichtbar

struct M { 
    friend void f() {} 
    M() { 
     f(); // error: 'f' was not declared in this scope 
    } 
}; 

int main() { 
    M m; 
} 

Live example

Sowohl g ++ 4.8 und clang3.4 scheitern, es zu kompilieren, weil f innerhalb M nicht sichtbar ist oder so sagen sie.

Allerdings gibt die Norm ein Beispiel eines ähnlichen Code

class M { 
    friend void f() { } // definition of global f, a friend of M, 
         // not the definition of a member function 
}; 

und sagt, dass

A friend Funktion in einer Klasse definiert ist in dem (lexikalischen) Umfang der Klasse in was es definiert ist.

(ISO/IEC 14882: 2011 11.3 Freunde [class.friend] p6, p7)

Daraus kann ich nicht verstehen, wie Compiler nicht f finden kann, die in derselben Klasse definiert ist, wo es ist benutzt.

Es ist irgendwie unwahrscheinlich, dass beide Compiler den gleichen Fehler haben.
Also, was habe ich vermisst?

+0

Wo haben Sie es erklärt? –

Antwort

12

Die Friend-Deklaration besagt, dass eine Funktion namens f im umgebenden Namespace ein Freund der Klasse ist; aber es führt den Namen f nicht in den Namespace ein. Es ist nicht verfügbar (außer durch argumentabhängige Suche), bis es im Namespace deklariert ist.

Die entsprechende Regel ist C++ 11 7.3.1.2/3:

Wenn eine friend Erklärung in einer nicht-lokalen Klasse zunächst eine Klasse oder Funktion den Freund Klasse deklariert oder eine Funktion ist ein Mitglied der innerster einschließender Namespace. Der Name des Freundes wird nicht durch qualifizierte Suche oder durch qualifizierte Suche gefunden, bis eine übereinstimmende Deklaration in diesem Namespacebereich bereitgestellt wird.

3

Dieses Zitat aus der C++ Standard-

A Friend-Funktion in einer Klasse definiert ist in dem (lexikalischen) Umfang der Klasse, in der sie definiert ist.

bedeutet folgende

9-Namenssuche nach einem Namen in der Definition einer Freunds Funktion (11.3) definiert inline in der Klasse Gewährung Freundschaft verwendet wird gehen Sie wie zum Nachschlagen in Elementfunktion beschrieben Definitionen.

Das ist jeder Name in der Funktion verwendet wird gesucht, ausgehend von der Klasse Umfang.

Die Funktion selbst ist jedoch im Namensraum nicht sichtbar, bis sie außerhalb der Klasse deklariert wird.

Also in Ihrem Fall ist es ausreichend, die Funktion vor der Klassendefinition

void f() {} 

struct M { 
    friend void f(); 
    M() { 
     f(); 
    } 
}; 

int main() { 
    M m; 
} 

Oder

void f(); 

struct M { 
    friend void f() {} 
    M() { 
     f(); 
    } 
}; 

int main() { 
    M m; 
} 
+0

@Kate Gregory Danke. Es ist ein Tippfehler aufgrund der Operation "Kopieren und Einfügen". –

+1

@ Jonathan Mee Wer hat dir erlaubt, meinen Beitrag zu bearbeiten ?! Tu das nicht mehr! –

+0

* Aaand * ... das war mein schlechtes. Danke, dass du es gefangen hast. –

-4
struct M { 
    friend void f() {} 
    M() { 
     f(); // error: 'f' was not declared in this scope 
    } 
}; 

int main() { 
    M m; 
} 

Der obige Code funktioniert perfekt zu erklären. (Anprobiert DEVC++) Auch Versuchen Sie, die Funktion innerhalb der Klasse nicht zu definieren, da sie möglicherweise keinen Bereich außerhalb der Klasse hat, z. B. in main(). Beim Versuch, f() von main() aufrufen, erhalten Sie eine Fehlermeldung, dass die Funktion nicht existiert. Definieren Sie daher die Funktion außerhalb der Klassen, indem Sie den Operator :: (falls erforderlich) verwenden, damit von keiner Stelle aus auf die Funktion zugegriffen werden kann. Access friend function defined in class

+2

Es funktioniert möglicherweise "perfekt" auf einem alten, nicht-compliant Compiler, aber die Frage besagt eindeutig, dass es nicht auf mindestens zwei modernen Compiler funktioniert. –

2

Die kritische Frage ist, unter welchen Umständen der Compiler in der Lage ist, Ihre Funktionserklärung zu finden. Für eine allgemeine friend-Funktion müssen Sie sie außerhalb der Klasse deklarieren, damit der Compiler sie finden kann.

Allerdings gibt es eine sehr nützliche Ausnahme: Wenn die friend-Funktion ein Argument der Klasse hat, kann sie die Funktion ohne zusätzliche Deklaration wegen argument-dependent name lookup finden.

Dieser Fall ist eigentlich sehr wichtig, weil normalerweise eine friend Funktion auf ein Objekt des Klassentyps zugreifen möchte.


Betrachten Sie das folgende Beispiel:

#include <iostream> 

struct M 
{ 
    friend void printI(int a) { 
     std::cout << a; 
    } 
    friend void print(const M& m) { // friend takes object of class type! 
     std::cout << "M"; 
    } 
    void foo() { 
     printI(2); // ERROR - requires declaration! 
     print(*this); // OK! 
    } 
}; 

int main() 
{ 
    M m; 
    m.foo(); 
    printI(2); // ERROR - requires declaration! 
    print(m); // OK 
} 
Verwandte Themen