private Variablen wo deklarieren



  • Hallo,
    da ich momentan mehr in C++ programmiere, wollte ich mich über die richtige Verwendung von Header und Source-Dateien informieren.

    Ich habe folgendes Mal vor ein paar Jahren gelesen:
    Am besten in die Header-Datei nur die Sachen schreiben, die public sein sollen, private Sachen können in der cpp-Datei angegeben werden. Vorteil, damit reduziert man die Includes in der Header-Datei auf ein Minimum. Somit muss sich bei anderen Dateien, die diese Header-Datei verwenden, nicht um die Verfügbarkeit von vielen anderen Header-Datei gekümmert werden, sondern nur um die wirklich notwendigen.

    Beispiel:
    Anstelle von:

    //Test.h
    class TestOld
    {
    public:
    	int publicVar;
    
    	void pubicMethod();
    
    private:
    	int privateVar;
    
    	void privateMethod();
    }
    

    Folgendes:

    //Test.h
    class TestNew
    {
    public:
    	int publicVar = 0;
    
    	void pubicMethod();
    }
    
    //Test.cpp
    #include "Test.h"
    
    int privateVar;
    
    void privateMethod()
    {
    	...
    }
    
    void TestNew::pubicMethod()
    {
    	...
    }
    

    Bis jetzt hat es gut funktioniert aber nun habe ich kurz aufeinander 2 Probleme durch dieses Vorgehen bekommen:

    • Als ich mit dem "TestNew"-Vorgehen eine Map in cpp definiert hatte, bekam ich beim ersten Zugriff ein Segmentation fault. Nachdem ich die Deklaration 1:1 von der cpp-Datei in die h-Datei kopiert habe, hat es funktioniert.
    • In zwei verschiedenen cpp-Dateien zwei verschiedener Klassen habe ich den selben Variablen-Namen verwendet. Beim Linken habe ich dann Probleme bekommen, da der Linker durch die Duplikation nicht wusste, welche Variable er verbinden sollte.

    Deshalb fange ich momentan an, an diesem Vorgehen zu zweifeln. Vielleicht habe ich das ja gar nicht gelesen, sondern es waren meine Gedanken, die völlig falsch sind?
    Deshalb wollte ich hier mal nachfragen um meinen Code zu verbessern.

    Vielen Dank für eure Hilfe



  • Deine Variante ist total falsch.
    Ich weiß nicht, wer dir das gesagt hat, aber vergiss das!
    Die Variable im Sourcefile ist global und wird für jede Klasse verwendet.
    Private Variablen einer Klasse müssen in die Klassendefinition!



  • Man kann auch das pimpl idiom verwenden um private elemente zu "verstecken"
    http://www.gotw.ca/gotw/024.htm



  • firefly schrieb:

    Man kann auch das pimpl idiom verwenden um private elemente zu "verstecken"
    http://www.gotw.ca/gotw/024.htm

    Darauf wollte der TE anscheinend auch hinaus, macht es aber völlig verkehrt.



  • Hallo,
    danke für eure Antworten.

    Nathan schrieb:

    Deine Variante ist total falsch.
    Ich weiß nicht, wer dir das gesagt hat, aber vergiss das!
    Die Variable im Sourcefile ist global und wird für jede Klasse verwendet.

    Das habe ich befürchtet. Dann werde ich mir das schleunigst wieder abgewöhnen.

    Aber eine interessens Frage bleibt: Wieso bekam ich bei beim Zugriff (insert) auf eine Map ein segmentation fault, wenn ich die Deklaration (std::map<int, int> test;) in die cpp-Datei schreibe und nicht in die h-Datei?

    firefly schrieb:

    Man kann auch das pimpl idiom verwenden um private elemente zu "verstecken"
    http://www.gotw.ca/gotw/024.htm

    hm ja, klingt interessant. Das Vorgehen so habe ich noch nie gesehen. Wie gängig ist das?



  • Hambrana schrieb:

    hm ja, klingt interessant. Das Vorgehen so habe ich noch nie gesehen. Wie gängig ist das?

    Kaum noch.
    Als es relativ neu war, hat's jeder gemacht. Es war halt cool.
    Aus dem völlig unverständlichen Wunsch heraus, den Mitprogrammieren gegenüber Details zu verstecken. (Erinnert mich an die Unsitte, die Membervariablen erst nach allen Methoden zuzugeben.)

    Kommt aber zu recht noch vor, z.B. um längere Binärkompatibilität gegenüber alternden eigenen Bibliotheken zu haben oder sowas.



  • Wird das nicht zusätzlich verwendet um die Compilierzeit zu minimieren? Bei Änderungen der Implementationsklasse würd' ja nur eine Übersetzungseinheit neu übersetzt. Da muss man nicht das halbe Projekt neu übersetzen.



  • volkard schrieb:

    Hambrana schrieb:

    hm ja, klingt interessant. Das Vorgehen so habe ich noch nie gesehen. Wie gängig ist das?

    (Erinnert mich an die Unsitte, die Membervariablen erst nach allen Methoden zuzugeben.)

    Ich mache das so.
    Finde das für den User praktischer.
    Wenn der mal eben nach sehen will, wie die Signatur einer bestimmten Funktion ist, will er nicht an haufenweise privaten Variablen vorbeiscrollen (ich gehe jetzt mit "User" von meiner Sicht aus).



  • Jo, zb. Boost.Spirit Code in einer häufig verwendeten Headerfile kann eine halbe Katastrophe sein.
    Oder zb. Windows.h verstecke ich persönlich sehr gerne, das eklige Monster will niemand haben.



  • Sone schrieb:

    Wird das nicht zusätzlich verwendet um die Compilierzeit zu minimieren? Bei Änderungen der Implementationsklasse würd' ja nur eine Übersetzungseinheit neu übersetzt.

    Die Zeiten sind eher um.
    Kauf lieber nen I7. Und mach LTO an, weil Du *zu viel* Rechenpower hast.
    Kaufst Du Dir Compilezeit, indem Du Laufzeit opferst?
    Naja, hoffe, nicht auf regelmäßiger Basis.
    Und darüberhinaus, was auch früher schon galt, wie oft ändern sich denn Attribute? Gell, nicht so arg oft. An den Methoden fummelt man dauernd.



  • Nathan schrieb:

    volkard schrieb:

    Hambrana schrieb:

    hm ja, klingt interessant. Das Vorgehen so habe ich noch nie gesehen. Wie gängig ist das?

    (Erinnert mich an die Unsitte, die Membervariablen erst nach allen Methoden zuzugeben.)

    Ich mache das so.
    Finde das für den User praktischer.
    Wenn der mal eben nach sehen will, wie die Signatur einer bestimmten Funktion ist, will er nicht an haufenweise privaten Variablen vorbeiscrollen (ich gehe jetzt mit "User" von meiner Sicht aus).

    Die Signatur zeigt mir doch die IDE an. Oder ich suche im Header mit Strg+F.
    Wenn ich den Header lese, will ich schauen, was unter der Haube ist.



  • Ethon schrieb:

    Jo, zb. Boost.Spirit Code in einer häufig verwendeten Headerfile kann eine halbe Katastrophe sein.

    Attribute, die Boost.Spirit benötigen? Oder eher Methoden, die man auch so rausschubsen könnte?

    Ethon schrieb:

    Oder zb. Windows.h verstecke ich persönlich sehr gerne, das eklige Monster will niemand haben.

    Naja, geht auch mit einem optimistischen typedef™ im Header und static_assert in der cpp-Datei.



  • volkard schrieb:

    Wenn ich den Header lese, will ich schauen, was unter der Haube ist.

    Weiß nicht... Find das Argument etwas seltsam. Zu 99% will ich das eher nicht. Wir haben in unserem Projekt tausende Klasse und Millionen Zeilen Code. Die allermeisten davon will ich einfach nur benutzen und da interessieren mich die Details sicher nicht, bis ich da was genauer verstehen oder ändern muss. Aber dann kann ich eben runterscrollen und mir die Variablen anschauen, wenn es sein muss.



  • Mechanics schrieb:

    volkard schrieb:

    Wenn ich den Header lese, will ich schauen, was unter der Haube ist.

    Weiß nicht... Find das Argument etwas seltsam. Zu 99% will ich das eher nicht. Wir haben in unserem Projekt tausende Klasse und Millionen Zeilen Code. Die allermeisten davon will ich einfach nur benutzen und da interessieren mich die Details sicher nicht, bis ich da was genauer verstehen oder ändern muss. Aber dann kann ich eben runterscrollen und mir die Variablen anschauen, wenn es sein muss.

    Wenn ich vorher die Attribute lese, dann kann ich mir bei jedem Methodennamen schon recht gut vorstellen, was die Methode macht, wie schnell das sein wird wo sie Probleme haben wird. Es fällt mir leichter, mit der Klasse zusammenzuarbeiten.
    Ok, hängt vom Gebiet ab. Die Attribute von GUI-Klassen interessieren mich gar nicht.


Log in to reply