Greifen Sie auf die in der Klasse definierte Freundesfunktion zu
Lesezeit: 3 Minuten
Es gibt einen solchen Code:
#include <iostream>
class A{
public:
friend void fun(A a){std::cout << "Im here" << std::endl;}
friend void fun2(){ std::cout << "Im here2" << std::endl; }
friend void fun3();
};
void fun3(){
std::cout << "Im here3" << std::endl;
}
int main()
{
fun(A()); // works ok
//fun2(); error: 'fun2' was not declared in this scope
//A::fun2(); error: 'fun2' is not a member of 'A'
fun3(); // works ok
}
Wie greife ich auf die Funktion fun2() zu?
+1: Gut formulierte Frage.
– Leichtigkeitsrennen im Orbit
16. Oktober 2011 um 17:26 Uhr
Wir sehen diese Art von Code im intelligenten Zeiger von boost: intrusive_ptr, was mich zunächst verwirrte, was das sein sollte. Für mich macht es keinen Sinn, es so zu definieren, sondern irgendwo im Bereich einen Freund zu definieren und einen Prototyp in der Klassenbereichsdeklaration als Freund zu markieren, was besser lesbar ist!
Obwohl Ihre Definition von fun2tut Definieren Sie eine “globale” Funktion anstelle eines Members und machen Sie sie zu einer friend von A Gleichzeitig fehlt Ihnen immer noch eine Deklaration derselben Funktion im globalen Geltungsbereich selbst.
Das bedeutet, dass kein Code in diesem Bereich eine Ahnung davon hat fun2 existiert.
Das gleiche Problem tritt z funaußer dass die argumentabhängige Suche die Funktion übernehmen und finden kann, da ein Argument vom Typ vorhanden ist A.
Ich empfehle stattdessen, Ihre Funktionen auf die übliche Weise zu definieren:
Beachten Sie das jetzt alles funktioniert (außer fun3 weil ich es nie definiert habe).
CB Bailey
Der Grund, warum Sie anrufen können fun ist das die Friend-Deklaration innerhalb der Klasse A macht es nur über argumentabhängige Suche sichtbar. Andernfalls machen Friend-Deklarationen die Funktionen, die sie deklarieren, nicht automatisch außerhalb des Klassenbereichs sichtbar, in dem sie erscheinen.
Sie müssen eine Deklaration im Namespace-Bereich oder innerhalb hinzufügen main zu machen fun2 sichtbar darin main.
Z.B
void fun2();
fun3 ist innen sichtbar main weil ihre Definition (außerhalb der Klasse) auch eine Deklaration ist, die sie sichtbar macht main.
ISO/IEC 14882:2011 7.3.1.2:
Der Name des Freundes wird nicht durch unqualifiziertes Nachschlagen (3.4.1) oder durch qualifiziertes Nachschlagen (3.4.3) gefunden, bis eine übereinstimmende Deklaration in diesem Namensraumbereich bereitgestellt wird (entweder vor oder nach der Klassendefinition, die Freundschaft gewährt).
3.4.2 (Argumentabhängige Namenssuche) / 4:
Alle Friend-Funktionen im Namensraumbereich oder Friend-Funktionsvorlagen, die in zugeordneten Klassen deklariert sind, sind in ihren jeweiligen Namensräumen sichtbar, selbst wenn sie während einer gewöhnlichen Suche (11.3) nicht sichtbar sind.
Das Platzieren der Deklaration im globalen Namensraum löst das Problem, aber das Platzieren in der Hauptfunktion erzeugt einen Linker-Fehler. Danke.
– scdmb
16. Oktober 2011 um 17:18 Uhr
@scdmb: Ich bin überrascht über den Linker-Fehler, er sollte gültig sein.
– CB Bailey
16. Oktober 2011 um 17:21 Uhr
Nein, Platzierung der Definitionserklärung in mainverursacht a Compiler Error. Was Charles vorgeschlagen hat, ist richtig. Und das nächste Mal stellen Sie bitte jedes Mal einen Testfall bereit, wenn Sie mit einem solchen Fehlerbericht zurückkommen. In Ihrem C++-Buch finden Sie den Unterschied zwischen einer Deklaration und einer Definition.
– Leichtigkeitsrennen im Orbit
16. Oktober 2011 um 17:21 Uhr
@TomalakGeret’kal: Ich bekomme auch den Linker-Fehler, kannst du mir helfen, wo ich es falsch verstanden habe?
– CB Bailey
16. Oktober 2011 um 17:24 Uhr
@Charles: codepad.org Mal sehen! Hat meine Arbeitspaste Ihren Vorschlag zur Abgabe der Erklärung nicht genau wiedergegeben? main?
– Leichtigkeitsrennen im Orbit
16. Oktober 2011 um 17:25 Uhr
9157800cookie-checkGreifen Sie auf die in der Klasse definierte Freundesfunktion zuyes
+1: Gut formulierte Frage.
– Leichtigkeitsrennen im Orbit
16. Oktober 2011 um 17:26 Uhr
Wir sehen diese Art von Code im intelligenten Zeiger von boost: intrusive_ptr, was mich zunächst verwirrte, was das sein sollte. Für mich macht es keinen Sinn, es so zu definieren, sondern irgendwo im Bereich einen Freund zu definieren und einen Prototyp in der Klassenbereichsdeklaration als Freund zu markieren, was besser lesbar ist!
– Gabriel
14. Juni 2014 um 14:59 Uhr