"friend" in C++

Tronar

aus Überzeugung altmodisch
Hallo!
Nikolaus ist vorbei, heute herrscht wieder der Ernst des Arbeitslebens. Folgende Situation:

Ich habe hier den Quellcode eines größeren Programmpakets, soll aber keine großen Änderungen daran vornehmen, nur kleine Ergänzungen. (Mit meiner geringen Programmiererfahrung traut man mir da nicht so recht :-) )
Was ich will, ist, eine Klasse davon für ein spezielles, selbstgeschriebenes Testprogramm zu verwenden. Dieses habe ich in einer separaten Datei stehen, darin wird eine Instanz der Klasse erzeugt, aber leider kann ich nicht auf die privaten Daten des Objekts zugreifen. Dazu müßte man im besagten Programmpaket Unmengen Get- und Set-Methoden anbringen, und für einige dieser Daten ist das ausdrücklich nicht erwünscht.

Deshalb dachte ich an eine "friend"-Funktion. Ich habe also im Programmpaket eine Zeile hinzugefügt: friend void access_Radiator_class ();
Das Programmpaket läßt sich auch mühelos kompilieren. Aber mein Programm mit der Implementation dieser Funktion haut mir der g++ um die Ohren, von wegen, diese und jene Variable sei "private" und ich hätte ja überhaupt kein Recht zu gar nichts.

Ist "friend" eventuell gar nicht dateiübergreifend einsetzbar? Oder was ist los?

Stillt meinen Wissenshunger!
Tronar
 
du musst in der Klasse die du benutzen willst, deine Testclass als friend Klasse deklarieren.
Also:
Code:
class Klasse {
    friend class TestKlasse;
private:
    int private;
};

jetzt kann deine TestKlasse auf Klasse zugreifen
 
Es ist definitiv so, wie ilb es geschrieben hat. Was meldet g++ genau?
Folgendes:
g++ <optionen> make_TRD_hist.C
CbmTrdRadiator.h: In function ‘void access_Radiator_class()’:
CbmTrdRadiator.h:144: error: ‘Float_t CbmTrdRadiator::fSpBinWidth’ is private
make_TRD_hist.C:38: error: within this context
CbmTrdRadiator.h:159: error: ‘const Int_t CbmTrdRadiator::fNMom’ is private
make_TRD_hist.C:39: error: within this context
usw.

CbmTrdRadiator ist besagte Klasse, access_Radiator_class ist die Funktion, die eine Freundin sein möchte.

Diese Funktion ist nicht Teil einer Klasse. Das kann ich auch machen, aber es sollte doch egal sein, ob ich einzelne Funktionen oder ganze Klassen zu Freunden erkläre. Daher verstehe ich "ilb"s Hinweis nicht ganz.

Vielleicht versuche ich heute abend mal, ein komplettes Minimalbeispiel zusammenzustellen, um zu sehen, ob es auch dann noch scheitert.

MfG
Tronar
 
friend ist nich transitiv. Das heisst, du kannst deine funktion access_Radiator_class nicht, wenn ich das richtig verstanden habe, als friend der klasse CbmTrdRadiator deklarieren.
das musst du innerhalb der klasse CbmTrdRadiator machen.
Also folgendes geht nicht:

Code:
class PrivateClass {
private:
    int totalgeheim;
};

friend void access_PrivateClass() {
    PrivateClass p;
    p.totalgeheim; // GEHT NICHT ;)
}

Das klappt nicht. ;) du musst das wie folgt machen:

Code:
class PrivateClass {
    friend class AccessMe;
private:
    int totalgeheim;
};

class AccessMe {
public:
    void accessPrivateClass()
    {
        PrivateClass p;
        p.totalgeheim; // das geht
    }
};
 
Als Faustregel um sich das ganze leichter merken zu können musst du nur immer daran denken, dass friends die Datenkapselung untergraben können. Deshalb muss das ganze irgendwie geregelt werden. Nur die Klasse selbst darf sich ihre Freunde aussuchen. Sonst könnte ja irgendwer daher kommen und sich als Freund deklarieren und an private Daten kommen! Nicht Transitivität bedeutet, dass man Freundschaft nicht einfach weiter geben darf. Aus A freund von B. B freund von C, folgt nicht,A freund von C. Im Grunde genommen alles wie im richtigen Leben. :)

Wenn du willst, kann ich dir auch n bsp schicken, welches ich gestern auch zur Sicherheit zusammengeschustert habe. :)
 
Hallo, vimix, hallo ilb,
entschuldigt bitte die späte Antwort. Also, Ihr habt mich ein bißchen mißverstanden. Was ich programmiert habe, sieht etwa so aus, um Eure Nomenklatur zu gebrauchen:

Datei minA.h:
Code:
class PrivateClass {
    friend void access_PrivateClass();
private:
    int totalgeheim;
};

Datei minA.C:
Code:
#include "minA.h"

int main()

{ PrivateClass* x = new PrivateClass(); }

Datei minB.C:
Code:
#include <iostream>
#include "minA.h"

PrivateClass c;

void access_PrivateClass()

{ c.totalgeheim=7;
  std::cout << c.totalgeheim;
}

int main()

{ access_PrivateClass(); }

Das Dumme ist nur, daß dieses Minimalbeispiel problemlos kompiliert (und auch läuft).
"Meine" Funktion in minB.C "sieht" die privaten Daten der Klasse.
Das ist wohl wieder so ein Fall, bei dem ein ganz anderer Fehler gemeldet wird, als wirklich drin ist. (Das ist eine der häßlichen Seiten von C++.)

Z. Zt. habe ich aber diese Programmieraufgabe auf die lange Bank geschoben und erst mal was anderes in Arbeit. Mein Chef wäre zwar glücklich, wenn ich beides noch vor Weihnachten schaffe, aber ich bin da pessimistisch.

Danke jedenfalls für Eure Ratschläge
Tronar
 
Dein Beispiel definiert lediglich die Funktion als friend. Das bedeutet, dass Du im Grunde eine nicht-Klassenfunktion access_PrivateClass() schreibst, die in Deinem Beispiel auf das globale Object c zugreift. Das ist soweit auch korrekt. Aber es loest Dein Problem nicht.

Wie schon vorher mit Beispielcode von ilb deutlich gemacht wurde, muesstest Du die zugelieferte Klasse anpassen, damit Du auf die privaten Member zugreifen darfst.

Einen anderen Weg gibt es nicht.
 
Zurück
Oben