new reserviert nicht genug Speicher?



  • Moin Leute,
    mir stellt sich folgendes Problem:

    Was alles vorhanden ist:
    Ich habe versucht den Code auf das Wesentliche zu reduzieren.

    //==========================================================================
    // teile.h: Polomorphie am Beispiel einer Teileverwaltung
    //--------------------------------------------------------------------------
    
    //==========================================================================
    // Typdeklarationen
    //==========================================================================
    typedef FILE * fp_t; // Dateizeiger
    typedef unsigned long int uli_t; // grosse Ganzzahl n >= 0
    typedef long int li_t; // grosse Ganzzahl n +/-
    
    //==========================================================================
    // globale Konstanten
    //==========================================================================
    
      #define  BZL  20                // Laenge Textfeld bez fuer Teilebezeichnung
    
    //==========================================================================
    // teil: oberste abstrakte Basisklasse für alle abgeleiteten Klassen
    //==========================================================================
    class teil
      {
        friend class tverw; // Verwaltungsklasse 'tverw' hat vollen Zugriff
    
      protected:
        int wgrp;
        char bez[21];
        uli_t tnr;
        li_t best;
        float preis;
        int matr;
    
      public:
        //Konstruktor
        teil( fp_t );
      }; // class teil
    
    teil::teil( fp_t fp )
      {
        for( int i = 0; i < 2; ) // 2 Zeilen verwerfen
          {
            if( fgetc( fp ) == '\n' ) { i++; }
          } // for( int i = 0; i < 2; )
        fscanf( fp, "%d""%d""%f""%d", & tnr, & best, & preis, & matr );
        cout << tnr << "\t" << best << "\t" << preis << "\t" << matr; // funktioniert is hierher
      }
    
    //==========================================================================
    // mutter: von teil abgeleitete konkrete Klasse
    //==========================================================================
    class mutter : public teil
      {
      protected:
        int gewinde;
      public:
        //Konstruktor
        mutter( fp_t );
      }; // class mutter
    
    mutter::mutter( fp_t fp ) : teil( fp )
      {
        fscanf( fp, "%d", & gewinde );
        wgrp = 1;
      }
    
    //==========================================================================
    // tverw: Anwendungsklasse fuer die Teile-Datenbank
    //==========================================================================
    class tverw
      {
      protected:
        uli_t tAnz; // Teileanzahl: Anzahl der verschiedenen Teile in der Datendatei
        teil * * tArr; // Zeiger: Zeiger auf dynamsiches Feld mit tAnz Elementen aus Basisklassenzeigern
        bool fileError; // Dateistatus: true: Dateiöffnen fehlgeschlagen, false: Datei erfolgreich geöffnet
        unsigned int tAnz_counter;
        int wgrp_tmp;
        char tmpchar[81];
    
      public:
        //Konstruktoren
        tverw( char * );
    
        //Elementfunktionen
    
        virtual getFileError( void )
          { return fileError; }
    
      }; // class tverw
    
    //--------------------------------------------------------------------------
    // Funktionsdefinitionen der Klasse tverw
    //--------------------------------------------------------------------------
    tverw::tverw( char * filename )
      {
        fp_t fp; // FILE * - Zeiger 'fp' erstellen
        if( !( fp = fopen( filename, "r" ) ) )
          { fileError = true; }
        else
          {
            char inBuf[81];
            fileError = false;
            for( int i = 0; i < 3; ) // 3 Zeilen verwerfen
              {
                if( fgetc( fp ) == '\n' ) { i++; }
              } // for( int i = 0; i < 3; )
            fscanf( fp, "%d", & tAnz );
            tArr = new teil * [tAnz];
            for( int i = 0; i < 2; ) // 2 Zeilen verwerfen
              {
                if( fgetc( fp ) == '\n' ) { i++; }
              } // for( int i = 0; i < 2; )
    
            for( tAnz_counter = 0; tAnz_counter < 1; tAnz_counter++ ) // Teil für Teil einlesen... im Moment aber nur ein einziges
              {
                fscanf( fp, "%d", & wgrp_tmp );
                for( int i = 0; i < 1; ) // 1 Zeile verwerfen
                  {
                    if( fgetc( fp ) == '\n' ) { i++; }
                  } // for( int i = 0; i < 1; )
                tArr[tAnz_counter] = new mutter( fp );
              } // for()
    //Dieser cout- Befehl verursacht beim Compilieren das Problem:
            cout << tArr[tAnz_counter]->wgrp << tArr[tAnz_counter]->tnr << " | " << tArr[tAnz_counter]->best << " | " << tArr[tAnz_counter]->preis << " | " << tArr[tAnz_counter]->matr << " | " << tArr[tAnz_counter]->gewinde << endl;
    
          }
      }
    

    Wenn ich nun den ganzen Kram ohne den letzten cout- Befehl (auskommentieren) compiliere, gibt es offenbar keinerlei Probleme. Mit diesem cout- Befehl meckert der Compiler ""teile.h": E2316 'gewinde' ist kein Element von 'teil' in Funktion tverw::tverw(char 😉 in Zeile 285". Also habe ich mir mal das tArr[0] per Debug angeschaut und festgestellt, dass meines Erachtens das "tArr = new teil * [tAnz];" (Zeile 107) keinen Speicher für das "int gewinde" reserviert. Warum nicht? Ich bin der Meinung, die Konstruktoren korrekt aufgerufen zu haben...
    Ein "Ding" sehe ich noch: Warum muss ich bei dem o.g. cout- Befehl immer noch das "tArr[tAnz_counter]->" voranstellen? Die Klasse tverw (Teileverwaltung) ist doch "friend" von "teil" und sollte doch somit vollen Zugriff auf die einzelnen Elemente haben, oder?

    Danke schon mal für eure Hilfe!

    Gruß
    Christian

    P.S.: Es gehört nicht hierher aber wenn gerade jemand, der sich damit auskent "zuschaut": für den Fall, dass ich aus dem "float preis" ein "double preis" mache, was für einen Platzhalter muss ich mit fscanf benutzen? Tausend Dank an alle Helfenden!



  • Nachdem die for Schleife durchgelaufen ist steht tAnz_counter in diesem Fall auf 1, gültig ist aber nur Index 0.
    -> boom



  • Das ist korrekt, aber wie sieht es mit den Antworten zu meinen anderen Fragen aus? Hat jemand eine Idee?

    Gruß
    Christian



  • Öh, so wie ich das sehe, ist 'gewinde' in 'mutter' deklariert, nicht in 'teil'.



  • ChrisPHL schrieb:

    Ein "Ding" sehe ich noch: Warum muss ich bei dem o.g. cout- Befehl immer noch das "tArr[tAnz_counter]->" voranstellen? Die Klasse tverw (Teileverwaltung) ist doch "friend" von "teil" und sollte doch somit vollen Zugriff auf die einzelnen Elemente haben, oder?

    'friend' bedeutet nur, daß du die geschützten Elemente (private und protected) der entsprechenden Klasse lesen kannst. Um zuzugreifen, muß der Compiler trotzdem wissen, mit welchem Objekt du arbeiten willst (der Compiler kann schließlich nicht wissen, ob du tArr[0], tArr[500] oder ein lokal angelegte teil ausgeben willst.

    P.S.: Es gehört nicht hierher aber wenn gerade jemand, der sich damit auskent "zuschaut": für den Fall, dass ich aus dem "float preis" ein "double preis" mache, was für einen Platzhalter muss ich mit fscanf benutzen? Tausend Dank an alle Helfenden!

    Wenn du unbedingt fscanf() verwenden willst "%lf". Aber in C++ gibt es einen wesentlich sichereren Ansatz zur Ein/Ausgabe - IOStreams.



  • Joe_M. schrieb:

    Öh, so wie ich das sehe, ist 'gewinde' in 'mutter' deklariert, nicht in 'teil'.

    aber ich reserviere doch mit

    tArr[tAnz_counter] = new mutter(fp)
    

    Speicher für das gesamte Konstrukt einer Mutter (beinhaltet 'gewinde' und alles, was ein 'teil' hat - klärt mich auf, wenn das nicht so ist) wobei die Konstruktoren doch hübsch in umgekehrter Reihenfolge aufgerufen werden und tArr[tAnz_counter]->gewinde laut der einzulesenden Datei den Wert "4" haben sollte, oder nicht? 😕

    mutter::mutter(fp_t fp) : teil(fp) { // Gewinde und wgrp Werte zuweisen }
    

    Ich schreibe mit dem mutter::mutter- Konstruktor den Wert "4" in tArr[tAnz_counter]->gewinde und tArr[] kann die Klasse 'tverw' doch lesen... So ist meine 'Denke' an der Stelle.

    @CStoll:

    CStoll schrieb:

    'friend' bedeutet nur, daß du die geschützten Elemente (private und protected) der entsprechenden Klasse lesen kannst. Um zuzugreifen, muß der Compiler trotzdem wissen, mit welchem Objekt du arbeiten willst (der Compiler kann schließlich nicht wissen, ob du tArr[0], tArr[500] oder ein lokal angelegte teil ausgeben willst.

    Das will mir einleuchten. Manchmal sieht man den Wald vor lauter Bäumen nicht...

    CStoll schrieb:

    Wenn du unbedingt fscanf() verwenden willst "%lf". Aber in C++ gibt es einen wesentlich sichereren Ansatz zur Ein/Ausgabe - IOStreams.

    Um das als Fehlerquelle auszuschließen, habe ich den kompletten iostram-Kram testweise auf "FILE*..." umgestellt...

    Danke für Deine Hilfe!

    Gruß
    Christian



  • Die friend-Beziehung wird aber nicht vererbt. Dadurch, daß 'teil' friend-Zugriff bereitstellt, kannst du die in dieser Klasse angelegten Member problemlos lesen (und schreiben). Aber 'mutter' hat der Klasse tverw keinen friend-Zugriff gegeben, also kannst du deren Member nicht von außen sehen.



  • @CStoll & Co.
    Ihr könnt den Thread löschen, die Frage führt eher zu Verwirrung für diejenigen, die genau so wenig vom Stoff verstehen wie ich.

    Danke
    Christian


Anmelden zum Antworten