Grundlagen-Lücke in Sachen Klassendefinition



  • Hallo,

    In bisherigen Anwendungen habe ich die Erfahrung gemacht, dass es für das Speichern von structs (z.B. Name, Wert) sinnvoll ist, wenn diese eine feste Größe haben ...

    struct StockItem{
      char m_name[20];
      double m_value;
    }
    

    ... um sie wie folgt zu speichern ...

    StockItem si;
    strcpy(si.m_name, "Bayer");
    si.m_value = 47.11;
    
    ofstream outUP( ("Datei.dat", ios::binary);
    outUP.write( (char*) &si, sizeof(si) );
    

    Nun bin ich gerade dabei einige Grundlagen-Lücken in Sachen Klassendefinition zu schließen. Dazu habe ich ein gut kommentiertes kleines Beispiel gefunden.

    1  #ifndef StockItem_h
     2  #define StockItem_h 1
     3
     4  class StockItem {
     5
     6  public:
     7      // ctor
     8      StockItem( const char* name = "", double val = 0.0);
     9
    10      // copy ctor
    11      StockItem( const StockItem &right);
    12      // dtor
    13      virtual ~StockItem();
    14      // assignment operator
    15      const StockItem& operator=(const StockItem &right);
    16
    17      // public member functions
    18      virtual const char* getName() const;
    19      virtual void setValue( double val);
    20      virtual void setValue( const char* val);
    21      virtual double getValue() const;
    22
    23  private:
    24      // private member variables
    25      char *m_name;
    26      double m_value;
    27  };
    28
    29  #endif
    

    Wie muss ich dieses Beispiel anpassen (Member, Initialisierungsliste), um Objekte von fester Größe zu erhalten?

    By the way: Wieso finde ich bei der Suche nach 'Initialisierungsliste' keinen Eintrag. Gibt es ein sinnvolleren Suchbegriff?

    Gruß
    Leo



  • Wieso muss das Objekt eine feste Groesse haben?

    Wenn du statt

    char *m_name
    

    wieder

    char m_name[20]
    

    nimmst hast du eine feste Groesse der Member.



  • pli schrieb:

    Wieso muss das Objekt eine feste Groesse haben?

    Wenn du statt

    char *m_name
    

    wieder

    char m_name[20]
    

    nimmst hast du eine feste Groesse der Member.

    Das ist klar! Nicht klar ist, wie dann die Initialisierung aussehen muss.



  • Du musst nix weiter initialisieren. Durch m_name[20] wird vom Compiler automatisch dafuer gesorgt, dass du 20 byte fuer den Namen hast. Was da drin steht ist ja nicht wichtig. Im Konstruktor kannst du das ja mit memset(...) anpassen und alles mit Nullern fuellen.

    StockItem::StockItem( const char *name = "", double val = 0.0 ) : m_value(val)
    {
      memset( m_name, 0, 20*sizeof(char) ); //ok, sizeof(char)==1, aber ist sauberer so
      strcpy( m_name, name );
    }
    

    Oder verstehe ich dich falsch? Wenn ja, dann weiss ich nicht was du fuer ein Problem meinst.



  • Oder verstehe ich dich falsch? Wenn ja, dann weiss ich nicht was du fuer ein Problem meinst.

    Ja, alles bestens, danke!

    Gruß
    Leo



  • Es sei nicht unerwähnt, dass es nicht empfehlendswert ist dann eine Klasse (oder eine Struktur) mit

    outUP.write( (char*) &si, sizeof(si) ); // Böse, böse
    

    zu speichern. Im Allgemeinen gibt es da mannigfaltige Probleme sobald die Daten wieder eingelesen werden müssen und das einlesende Programm mit einem anderen Compiler (evtl. sogar nur einer anderen Version) oder auf einer anderen Plattform läuft. Generell (schon bei Strukturen) gibt es das Problem mit der Bytereienfolge (http://de.wikipedia.org/wiki/Endianess) und bei der genannten Klasse kommt noch (wegen der virtuellen Methoden) der vtable-Pointer dazu, der, je nach Compiler, mit in den Daten rumlümmelt. In der geschriebenen Datei hat der nix zu suchen und beim vergleichbaren Einlesen mit read() gibt es nur mit sehr viel Glück nicht heftig auf die Finger, wenn man den in der Instanz überschreibt.

    Also für alles was über einfachste Tests hinausgeht besser elementweise schreiben bzw. lesen, wenn möglich (oder ein Verdacht besteht, später mal andere Plattformen unterstützen zu wollen) sogar endianess-neutral.


Anmelden zum Antworten