Problem mit statischen Klassenelementen



  • Wenn du innerhalb der Klasse
    static int Variable;
    definierst musst du das ausserhalb der Klasse im globalen Bereich nochmal definieren, ohne static aber mit Klassenname.
    int Kontrollklasse::Variable;



  • Aha! Prima!
    Wusste nicht dass diese auch noch definiert werden musste.

    Aber noch einmal zum Klassenentwurf, da gesagt wurde dass dies nicht sinnvoll sei.
    Mir fällt einfach keine bessere Alternative ein.
    Ein Singleton währe doch unnötig.
    Oder übersehe ich da etwas?

    Vielen Dank!



  • Jester schrieb:

    Du mußt die Variable auch noch definieren, im Header steht nur die Deklaration.

    Definition und Deklaration sind bei int Variablen das Gleiche. In der Klasse steht auch eine Definition.



  • freak11 schrieb:

    Jester schrieb:

    Du mußt die Variable auch noch definieren, im Header steht nur die Deklaration.

    Definition und Deklaration sind bei int Variablen das Gleiche. In der Klasse steht auch eine Definition.

    Eine Definition reserviert auch den benötigten Speicher.

    extern int x; ist übrigens eine Deklaration und keine Definition. Es ist ergo nicht das gleiche.



  • Eine "Klasse" die ausschliesslich aus statischen Daten-Members und statischen Memberfunktionen besteht ist IMHO keine Klasse sondern eine Abschäulichkeit. Dazu gibt es seit Annbeginn der Zeit Funktionen. Pack sie in einen Namespace und gut.

    Dein Ansatz hat im Übrigen auch mit Objektorientierung IMO nichts zu tun.



  • hustbaer schrieb:

    Eine "Klasse" die ausschliesslich aus statischen Daten-Members und statischen Memberfunktionen besteht ist IMHO keine Klasse sondern eine Abschäulichkeit. Dazu gibt es seit Annbeginn der Zeit Funktionen. Pack sie in einen Namespace und gut.

    Dein Ansatz hat im Übrigen auch mit Objektorientierung IMO nichts zu tun.

    ..und ein Singleton scheint mir durchaus Sinnvoll in dieser Situation.
    Du nennst die Klasse ja schon "Kontrollklasse", - wie oft sieht man ein "...Manager" als Klassennamen für Signeltons?

    Was genau hast du mit deinem Konstrukt eigentlich vor? Wenn es sich, wie der Name andeutet, um eine Verwalterklasse oder eine Fassade handeln sollte, sprich einfach einer Klasse mit nur einer Instanz UND einem globalen Zugriffspunkt, dann ist das Singleton Pattern miho das richtige für dich.

    Aber ich bin gespannt was du noch vor hast mit der Klasse..



  • Nun, den Ansatz mit den statischen Daten gibt es ja schon. Siehe Monostate bzw. Borg-Pattern
    und hier
    http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=147&rl=1



  • Mir ist durchaus bewusst dass dies kein "richtiges" objektorientiertes Klassenmodell ist, sondern nur eine Art Namespace-Kapselung mit privaten Datenelementen.

    Ein Singleton ist meiner Meinung nach absolut unnötig, da jedes Objekt sowieso die gleichen Daten beinhaltet.
    Ich rufe die Methoden (oder korrekter gesagt Funktionen) der Klasse mehrere hundert Tausend Mal pro Sekunde auf.
    Da spielt es schon eine Rolle dass die Zugriffsmethoden eines Singletons mit Instanzvariablen nicht inlined sein können und ich jedes Mal den this-Zeiger der Singleton-Instanz holen muss.

    Meint ihr dass dies nicht Grund genug ist, und man auch in diesem speziellen Fall konsequent objektorientiert vorgehen soll?

    Vielen Dank für Eure Ratschläge!



  • Achja, die Deklaration und Definition des Konstruktors und Destruktors wie im Beispiel gezeigt ist natürlich unnötig, da eh keine Instanzen erzeugt werden sollten.



  • Senfgurke schrieb:

    Mir ist durchaus bewusst dass dies kein "richtiges" objektorientiertes Klassenmodell ist, sondern nur eine Art Namespace-Kapselung mit privaten Datenelementen.

    Wieso nimmst du nicht gleich einen Namespace dafür, anstatt eine class zweckzuentfremden?



  • CStoll schrieb:

    Wieso nimmst du nicht gleich einen Namespace dafür, anstatt eine class zweckzuentfremden?

    Weil ich die Klassenvariablen als private deklarieren kann.



  • Wenn's dir nur um die Datenkapselung geht, kannst du die Variablen auch hinter einem anonymen Namensraum verstecken.



  • CStoll schrieb:

    Wenn's dir nur um die Datenkapselung geht, kannst du die Variablen auch hinter einem anonymen Namensraum verstecken.

    Fu.h

    namespace Fu
    {
    	inline void bar();
    }
    

    Fu.cpp

    namespace
    {
    	int privat;
    }
    
    void Fu::bar()
    {
    	privat = 0;
    }
    

    Nutzer.cpp

    #include "Fu.h"
    	...
    	Fu::bar();
    	...
    

    Da kann der Linker die Funktion nicht auflösen.
    Ohne inline-Deklaration kann er es.



  • Hmm, hat jemand eine Idee warum der Linker da Probleme hat?



  • Auch wenn ich int privat in der .cpp auserhalb des anonymen Namensbereich deklariere und definiere kann der Linker die Funktion nicht auflösen.
    Hmm...



  • Senfgurke schrieb:

    Auch wenn ich int privat in der .cpp auserhalb des anonymen Namensbereich deklariere und definiere kann der Linker die Funktion nicht auflösen.
    Hmm...

    Hast du den Namespace in der Cpp datei vor den Funktionsnamen gepackt?



  • Erstens solltest du das "inline" nur angeben, wenn du die Funktion direkt im Header implementierst (damit sagst du dem Compiler, daß er den Funktionsinhalt direkt einkopieren soll statt einen Funktionsaufruf zu erzeugen - also bereitet er auch nichts für einen Funktionsaufruf vor, wenn es nicht nötig ist). Und zweitens ist es vermutlich besser, du öffnest im CPP auch den Namensraum:

    //foo.h
    namespace foo
    {
      void bar();
    }
    
    //foo.cpp
    #include "foo.h"
    namespace foo
    {
      namespace
      {
        int privat;
      }
    
      void bar()
      {
        privat = 4711;
      }
    }
    


  • Danke für die Vorschläge.

    CStoll schrieb:

    Erstens solltest du das "inline" nur angeben, wenn du die Funktion direkt im Header implementierst

    Ich glaube dass ist so nicht richtig.
    Gerade wenn ich die Funktion im Header definiere, wird sie implizit als inline deklariert.
    Wenn ich sie außerhalb definiere, muss ich sie manuell mit inline oder __forceinline deklarieren.

    Also wird bar() im Beispiel nicht als inline-Funktion vom Compiler behandelt.

    Vielleicht sollte ich das einfach in C implementieren.



  • Senfgurke schrieb:

    Danke für die Vorschläge.

    CStoll schrieb:

    Erstens solltest du das "inline" nur angeben, wenn du die Funktion direkt im Header implementierst

    Ich glaube dass ist so nicht richtig.
    Gerade wenn ich die Funktion im Header definiere, wird sie implizit als inline deklariert.

    Das ist (sorry) Bullsh**. Der Compiler sieht überhaupt nichts mehr von Headern, deshalb ist es ihm auch egal, ob du eine Funktion im Header oder im CPP-File definiert hast.

    Wenn du eine Funktion im Header definierst, mußt du sie als inline kennzeichnen, sonst könntest du Probleme von Linker bekommen (Mehrfachdefinitionen). Wenn du die Funktion im Header nur deklarierst und im CPP-File definierst, brauchst du kein inline (und wie du selbst gesehen hast, ist es eher hinderlich).

    PS: Und implizit als inline deklariert werden nur Klassenmethoden, die du innerhalb der Klassendefinition gleich definierst.

    PPS: Egal was du machst, die letzte Entscheidung über "inline oder nicht?" trifft in jedem Fall dein Compiler.



  • Stimmt.
    Ich habe im Delirium von Definition im Header gesprochen, obwohl ich die Definition von Klassenmethoden innerhalb der Klassendefinition meinte.

    Mit __forceinline kann ich doch aber den compiler zwingen (wenn es fehlerfrei möglich ist) die Funktion als inline zu behandeln.
    Nur kann ich dass auch in deinem Beispiel nicht umsetzen.


Anmelden zum Antworten