Namespace + Class



  • Nein, das ist sozusagen ein Ersatz dafür. Manchmal braucht man das auch, weil der header der anderen Klasse das benötigt, was aktuell erst definiert wird. Durch die Vorwärts-Deklaration wird dieser Zyklus dann aufgebrochen.

    Allerdings kann man mit einer Klasse, die nur durch eine forward-Deklaration bekannt gemacht wurde nicht alles machen. Du kannst nur Pointer und Referenzen auf diese Klasse definieren, aber keine Methoden davon aufrufen oder Objekte der Klasse erzeugen. Dafür benötigt der Compiler nämlich Informationen, die nur in der vollständigen Deklaration der Klasse enthalten sind.



  • Ok, danke das habe ich verstanden.

    Nun begreife ich aber folgendes Problem nicht:

    datei1.hpp:

    namespace test{
    class klasse1{
    private:
    .....
    
    public:
    friend inline klasse1 f(const klasse1&);
    }
    }
    
    #include "datei1.cpp"
    

    datei1.cpp:

    namespace test{
    inline klasse1 f(const klasse1 &a){
    ...
    }
    }
    

    datei2.hpp

    namespace test{
    class klasse2{
    private:
    .....
    
    public:
    friend inline klasse2 f(const klasse2&);
    }
    }
    
    #include "datei2.cpp"
    

    datei2.cpp:

    namespace test{
    int g(int a){
    int m = f(....);
    ...
    }
    }
    

    Dann sagt g++-4.1.1: "f is not defined in this Scope".
    Warum?



  • Weil f ein Mitglied von klasse1 ist, keine freistehende Funktion. Du brauchst ein Objekt, um sie aufzurufen.

    Desweiteren definierst Du in datei1.cpp nicht die in datei1.h deklarierte Funktion, sondern eine neue, freistehende Funktion, die allerdings in datei2.cpp nicht bekannt ist (da in keinem Header deklariert)

    Und drittens bedeutet inline, dass beim Aufruf der Funktion der Code der Funktion selbst eingesetzt werden soll (also eben kein Aufruf stattfindet), und das funktioniert sowieso nicht wenn der Code nur in einer Übersetzungseinheit bekannt ist. Was möchtest Du überhaupt erreichen?



  • Weil f ein Mitglied von klasse1 ist, keine freistehende Funktion. Du brauchst ein Objekt, um sie aufzurufen.

    Ok, das ist mir nicht klar, denn die Funktion ist als friend deklariert und das bedeutet, dass sie ohne Objekt direkt aufgerufen werden kann. Wenn ich das richtig verstanden habe.

    Desweiteren definierst Du in datei1.cpp nicht die in datei1.h deklarierte Funktion, sondern eine neue, freistehende Funktion, die allerdings in datei2.cpp nicht bekannt ist (da in keinem Header deklariert)

    Das verstehe ich nicht. Ich deklariere die friend-Funktion f in datei1.hpp und implementiere sie in datei1.cpp. Was ist daran verschieden?

    Und drittens bedeutet inline, dass beim Aufruf der Funktion der Code der Funktion selbst eingesetzt werden soll (also eben kein Aufruf stattfindet), und das funktioniert sowieso nicht wenn der Code nur in einer Übersetzungseinheit bekannt ist. Was möchtest Du überhaupt erreichen?

    Na ja gut, was inline ist und nicht, entscheidet sowieso der Compiler. Ich baue eine Klassenbibliothek aus rund 1500 Dateien, die möglischst Laufzeiteffizient sein soll. Zwei Klassen benutzen eben die gleiche Funktion f, um sie nicht zweimal zu implementieren, möchte ich diese Funktion aus der anderen Klasse verwenden. Deswegen friend. Ist das falsch?



  • hjdt schrieb:

    ...denn die Funktion ist als friend deklariert und das bedeutet, dass sie ohne Objekt direkt aufgerufen werden kann. ...

    static , nicht friend . friend ist dazu da, um Beziehungen zwischen Klassen und deren Elementen herzustellen (d.h. man kann z.B. durch Operator-Überladung dafür sorgen, dass ein cout -Objekt das eigene Objekt als rhs-Operand übernehmen kann, obwohl in cout natürlich keine Überladung hierfür vorgenommen wurde). Bei static wird kein Objekt für den Aufruf benötigt, allerdings sieht der Aufruf dann so aus:

    klassenname::funktionsname();
    

    Das mit dem inline : Je nach Compiler-Einstellung kann man den Compiler darum bitten, das so effizient wie möglich zu handhaben, aber wenn wirklich alle Funktionen als inline gelten, hast du zwar eine unheimlich laufzeiteffiziente Bibliothek, aber der Preis dafür ist hoch: viel zu viel Speicher (ist allerdings nur eine Warnung meinerseits, hab ja nicht alle 1500 Dateien hier zum durchsehen).



  • Ah, ja sicher, das friend habe ich übersehen, sorry.
    Liegt vermutlich daran dass datei1.hpp in datei2.cpp nicht inkludet wird.



  • LordJaxom schrieb:

    Ah, ja sicher, das friend habe ich übersehen, sorry.
    Liegt vermutlich daran dass datei1.hpp in datei2.cpp nicht inkludet wird.

    Doch habe ich, es funktioniert aber troetzdem nicht.



  • Du hast da was falsch verstanden. Du mußt nicht die cpp-Dateien in die Header includen, sondern umkegehrt. cpp-Dateien werden nie includet.



  • Jester schrieb:

    Du hast da was falsch verstanden. Du mußt nicht die cpp-Dateien in die Header includen, sondern umkegehrt. cpp-Dateien werden nie includet.

    Das ist schon klar, das steht ja auch nicht da.

    Apropos, ich habe gerade festgestellt, dass das Problem erst mit dem gcc-4.1.0 beginnt, vorher lässt sich alles prima übersetzen,



  • hjdt schrieb:

    Jester schrieb:

    Du hast da was falsch verstanden. Du mußt nicht die cpp-Dateien in die Header includen, sondern umkegehrt. cpp-Dateien werden nie includet.

    Das ist schon klar, das steht ja auch nicht da.

    Naja, in dem Beispiel, das Du gepostet hast steht's halt falschrum drin.


Anmelden zum Antworten