'Friend' funktioniert nicht

Hallo!
In meinem C+±Buch habe ich gelesen, wenn ich vor eine Memberfunktion einer Klasse friend schreibe, wird diese Memberfunktion zu einer globalen Funktion, die jedoch auf Variablen und Funktionen im Privat-Bereich der Klasse in der die ursprüngliche Memberfunktion steht zugreifen darf. Ich habe dazu ein kleines Beispiel geschrieben. Allerdings bekomme ich die Fehlermeldung, dass die Private Variable nicht deklariert sei. Ein wenig hat der Compiler schon recht, da sie weder global noch lokal in der ursprünglichen Memberfunktion deklariert ist, aber in der Klasse!
So sieht das Headerfile aus:

#include

class Klasse2{
public:
Klasse2(void);
friend void GlobaleFunktion(void);
~Klasse2(void);
private:
int MeineVariable;
};

Und so das CPP-File:
#include „Klasse2.h“
Klasse2::Klasse2(void){
MeineVariable = 10;
}

void GlobaleFunktion(void){
// Hier tritt der Fehler auf und ich weis nicht warum
MeineVariable += 2;
printf(„Neuer Wert der privaten Variablen: %d\n“, MeineVariable);
}

Klasse2::~Klasse2(void){
}

Weiss da mir vielleicht jemand einen Rat? habe ich etwas übersehen? Das Projekt habe ich als neue Konsolenanwendung mit MFC-Unterstützung erstellt.
Wenn ich die Friend-Funktion nur eine Meldung ausgeben lasse und dann die Funktion wie eine global definierte aus der main-Funktion heraus aufrufe, funktioniert es auch. Nur eben der nicht deklarierte Bezeichner.

Gruß Christian

Hallo,

Deine Interpretation ist falsch.

„GlobaleFunktion“ ist keine Memberfunction von Klasse2, denn niemand kann sich selbst zum Freund erklaeren und macht in diesem zusammenhand auch keinen Sinn, es sein denn man hat protected Vererbung mit Zugriffbeschränkung. Klasse2 willig nur ein, dass „GlobaleFunktion“ ein Freund von ihr ist und somit von aussen Zugriff auf ihre privaten Elemente hat. Deshalb muss es noch wie vor heissen irgendwie so heissen:

Klasse2Object.MeineVariable += 2;

Selbst das muss nicht immer gehen, denn es gibt bestimmte Konstellationen, wo „GlobaleFunktion“ als Anwender von Klasse2 arbeiten kann, wo so ein Zugriff trotz friend nicht erlaubt ist.

Ciao

Hi!
OK, du hast recht gehabt. Vielen Dank für die Info! Aber eine Frage bleibt da offen:
Im CPP-File in dem die main steht, steht auch nur die main. Die main ruft als erstes die Konstruktoren aller Klassen auf. Allerdings steht jetzt die globale Funktion die ur Friend der Klasse zwei erklärt wurde im gleichen CPP-File wie die ganzen Funktionen der Klasse zwei. Diese Globale Funktion die zur Friend der Klasse zwei erklärt wurde, wird als letztes in der main aufgerufen.
Dsa Problem: In der main wurde vor dem Aufruf der Friendfunktion bereits der Konstruktor für die Klasse zwei aufgerufen. Aber durch ausprobieren und deinem Hinweis bin ich drauf gekommen, dass ich dann in dieser Friendfunktion den Konstruktor der Klasse zwei erneut aufrufen muss. Ist das normal?

Christian

Hallo nochmal,

ich konnte Deinen letzten Ausfuehrungen nicht ganz folgen. Grundsaetzlich spielt es keine Rolle wo, wann und in welcher CPP Konstruktoren von Klassen mit „friend“-Zugriff aufgerufen werden. Auch der erneute Aufruf des Constructor’s in der Friend-Function ist mir nicht klar, was Du damit meinst. Dies erzeugt nur ein weiteres Objekt vom gleichen Type der Klasse.

Mit dem Schluesselwort „friend“ ist es grundsaetzlich so:

Zugriffsbeschraenkungen in C++ sind im Gegensatz zu anderen Sprachen immer Type-bezogen und nicht Object-bezogen wie z.B. in Smalltalk. D.h., zwei Objekte X,Y die beide vom Type Klasse A sind, koennen beide uneingeschränkt auf ihre protected und private Elemente zugreifen. Für zwei Objekte X,Y, die vom Type Klasse A,B sind, gilt dies nicht; genauso wenig wie fuer eine globale Funktion, die auf protected oder private data members der Objekte X,Y zugreifen moechte.

Mit der Keyword „friend“ kann nur im Prinzip jeder globalen Funktion wie auch Klasse Zugriff auf die Interna einer anderen Klasse gewaehrt werden. Es gelten aber Ausnahmen! Z.B. gilt dies fuer folgende Operatoren nicht: =, (), [], ->, usw.

Keine globale Funktion oder Klasse kann sich selbt zum Freund einer anderen Klasse erklären. Nur die Klasse selbst kann entscheiden, wer ihr Freund sein kann. Deshalb steht „friend“ immer in der Klassen-Deklaration und bezeichnet nur die Freunde und gibt nicht an, das es members der Klasse selbst sind. Member Functions einer Klasse haben ohnehin Zugriff auf den „geschuetzten“ Bereich.

Des weiteren ist „friend“ nicht transitiv. D.h. der Freund meines Freundes ist nicht automatisch mein Freund.

Die Starken von C++ gegenueber Java z.B. liegen in der hybriden Struktur der Sprache (C incl.) und in Schluesselwoertern wie „friend“ z.B… „friend“ gehoert eigentlich zu den schmutzigen Sprachbestandteilen und kann bzgl. Vererbung und Polymorphie Probleme bereiten und steht der objektorientierten Idee im Weg, da zugunsten eines erheblichen Laufzeitvorteils die strenge Datenkapselung aufgeweicht wird. Es gibt wie immer Ausnahmen, aber ich wuerde die Verwendung von „friend“ wenn es geht, moeglichst vermeiden, da die Wartbarkeit einer Klasse ansonsten erheblich erschwert werden kann.

Ciao