Problem mit Konstruktor



  • Hallo,

    ich habe irgendwie ein Problem mit meinem Konstruktor.

    Ich habe die Oberklasse "Studenten" und die Unterklassen "Bachelor" und "Kosi"

    Ich habe den Kosi Konstruktor

    Kosi(name, firma)
    

    und den Bachelor Konstruktor

    Bachelor(name)
    

    Inhaltlich sind beide identisch, bis auf die Tatsache, dass mein Kosi noch ein Firmenname gespeichert wird.

    Nun zum Problem...

    rufe ich auf

    Kosi(name, firma)
    

    funktioniert alles einwandfrei.

    Rufe ich allerdings

    Bachelor(name)
    

    auf, dann wird irgendwie aus einem mir nicht nachvollziehbarem Grund

    Bachelor(void)
    

    aufgerufen und somit wird nichts gespeichert.

    Woran kann das liegen?



  • Vielleicht zeigst du mal deine Konstruktoren.



  • skizZ schrieb:

    Rufe ich allerdings

    Bachelor(name)
    

    auf, dann wird irgendwie aus einem mir nicht nachvollziehbarem Grund

    Bachelor(void)
    

    aufgerufen und somit wird nichts gespeichert.

    Zeig mal bitte den Konstruktoraufruf und die Signatur deiner Bachelor-Konstruktoren.

    Den C++ kann keinen Konstruktor ohne Parameter aufrufen, wenn Parameter übergeben werden (Dies würde zu einem Compilerfehler führen).



  • Hi, ich poste einfach mal meinen Code...

    Student.h

    #pragma once
    #include <string>
    #include <vector>
    using namespace std;
    
    class Student
    {
    protected:
      vector<Student> Studenten;
      string Name;
      string Firmenname;
      int Matrikelnr;
      std::vector<int> Pruefung;
    public: 
      Student(void);
      ~Student(void);
      Student(const string&);
      Student(const string&, const string&);
      friend class Kosi;
      friend class Bachelor;
      friend class Manager;
    };
    

    Student.cpp

    #include "Student.h"
    
    extern Student s;
    
    Student::Student(void)
    {
    }
    
    Student::~Student(void)
    {
    }
    
    Student::Student(const string& Name)
    {
      this->Name = Name;
    }
    
    Student::Student(const string& Name, const string& Firmenname)
    {
      this->Name = Name;
      this->Firmenname = Firmenname;
    }
    

    Manager.cpp

    #include "Manager.h"
    #include <iostream>
    #include <fstream>
    #include <string>
    
    extern Student s;
    
    Manager::Manager(void)
    {
      using namespace std;
      ifstream namen_dat( "Namen.dat", ios_base::binary );
      const int N = 30;
      char name_carray[N+1];
      name_carray[N] = 0; // sicheres End-Of-String
      while( namen_dat.read( name_carray, N ) ) // einen Datensatz lesen
      {
        string name = name_carray;
    	int rnd=rand()%100;
    	if(rnd > 29)
    	  Bachelor(name);
        if(rnd<30) 
    	{
    	  ifstream file;
          int zeile = 0;
          string fileName = "Firmen.txt";
          file.open(fileName.c_str());
          if(file)
          {
            string text; // Haupttext
            int zeile=rand()%37;
    		int zeilen = 0;
            while(!file.eof())
            {
              string txt; // Buffer
              getline(file, txt);
              text = txt + "\n";
              zeilen++;
              if(zeile == zeilen) // gesuchte Zeile erreicht
              {
                Kosi(name, text);
                break; // Zeile gefunden, Einlesen abbrechen
              }
            }
            file.close();
          }
        }
      }
      cout << s.Studenten.size();
    }
    
    Manager::~Manager(void)
    {
    }
    

    Kosi.h

    #pragma once
    #include "Student.h"
    #include <string>
    using namespace std;
    
    class Kosi : public Student
    {
    private:
      string Firmenname;
    public:
      Kosi(void);
      Kosi(const string&, const string&);
      ~Kosi(void);
    };
    

    Kosi.cpp

    #include "Kosi.h"
    
    extern Student s;
    
    Kosi::Kosi(void)
    {
    }
    
    Kosi::~Kosi(void)
    {
    }
    
    Kosi::Kosi(const string& Name, const string& Firmenname)
    : Student(Name, Firmenname)
    {
      s.Studenten.push_back(*this);
    }
    

    Bachelor.h

    #pragma once
    #include <string>
    #include "Student.h"
    using namespace std;
    
    class Bachelor : public Student
    {
    private:
    public:
      Bachelor(void);
      Bachelor(const string&);
      ~Bachelor(void);
    };
    

    Bachelor.cpp

    #include "Bachelor.h"
    
    extern Student s;
    
    Bachelor::Bachelor(void)
    {
    }
    
    Bachelor::~Bachelor(void)
    {
    }
    
    Bachelor::Bachelor(const string& Name)
    : Student(Name)
    {
      s.Studenten.push_back(*this);
    }
    

    Ziel der Übung: Daten aus Dateien zufallsgesteuert zusammenfügen.
    Mit dem Kosi funktioniert alles einwandfrei, nur mit dem Bachelor nicht.



  • Was passiert denn genau, wenn du den Bachelor -Konstruktor aufrufst? Geh doch mal mit dem Debugger durch und schau, wo nicht das passiert, das du erwartest. Beim Code sind mir zudem einige Dinge aufgefallen:

    vector<Student> Studenten;
    

    Innerhalb der Student -Klasse ist es eigentlich nicht sinnvoll, einen Container vom eigenen Typ zu haben. Vielleicht ein Container aus Zeigern, aber auch da stellt sich die Frage, ob der Student die anderen Studenten kennen soll.

    Die friend -Deklarationen solltest du wenn möglich vermeiden, da dadurch das Prinzip der Kapselung und dem Schutz der Interna umgangen wird. Wenn du protected -Member hast, können die abgeleiteten Klassen auch so zugreifen.

    extern Student s;
    

    Was ist mit dem? Wird der irgendwann definiert? Wieso überhaupt global?

    Es gibt noch einige weitere Dinge, aber das sollte fürs erste reichen...



  • Hi,

    alles klar, ich werde das alles mal beachten und nochmal durchgehen. Das mit dem Vektor ist natürlich wahr, den sollte ich in die Managerklasse packen 😕

    Also wenn ich den Bachelor aufrufe, ruft er Bachelor(void) auf 🙂

    Ich melde mich morgen nochmal, falls ich es nicht schaffen sollte.



  • Probier dein Problem auf etwas einfacheres zu abstrahieren. Das hat viel zu viel drin, was nichts zur Sache tut. Und wenn du das erst mal draussen hast, wirst du den Fehler sicher selber finden.

    btw:
    - using namespace im Header i.d.R böse.
    - Initialisierungsliste benutzen



  • Hi,

    habe es nun hinbekommen.
    allerdings habe ich nun noch eine Frage.

    In der Managerklasse habe ich folgenden Container in dem ich alle Studenten sammele

    vector<Student*> Studenten;
    

    Die Unterklasse Kosi hat als Attribute Name und Firme.
    Die Unterklasse Bachelor hat als Attribut nur den Namen.
    Die Superklasse Student hat als Attribut nur den Namen.

    So, wie kann ich nun von der Managerklasse aus abfragen, welcher gespeicherte Student ein Kosi ist bzw den Firmennamen ausgeben?

    Speichern tue ich sie auf diese Art

    Studenten.push_back(new Kosi(name, firma));
    
    Kosi::Kosi(const string& Name, const string& Firmenname)
    : Student(Name)
    {
      this->Firmenname = Firmenname;
    }
    
    Student::Student(const string& Name)
    {
      this->Name = Name;
    }
    


  • Das würde jetzt nur über einen dynamic_cast gehen.
    also

    Kosi* test = dynamic_cast<Kosi*>(Studenten[0]);
    if( test != 0) // dann ist es ein Kosi
    {
    }
    


  • Allerdings kann ich damit noch immer nicht auf das Kosi Attribut Firmenname zugreifen 😞



  • skizZ schrieb:

    Allerdings kann ich damit noch immer nicht auf das Kosi Attribut Firmenname zugreifen 😞

    Doch, kannst du, indem du den Zeiger dereferenzierst.


Anmelden zum Antworten