eigener Datentyp soll als Attribut einer anderen eigenen Klasse verwendet werden



  • Danke übrigens für die schnellen Antworten. Hab die Reihenfolge geändert

    #include <iostream>
    #include <string>
    using namespace std;
    
    class KURS;
    class BENUTZER{ 
    	private:
    		string NAME;            // Name
    		long MATR_NR;           // Matrikelnummer
    		KURS BELEGT_KURS;       // Kurs, der belegt werden soll
    	public:
    		BENUTZER(string NM, long MNR); // Konstruktor: Name und Matr.Nr. als Eigenschaft,
    		int WAEHLE_KURS(KURS); // ACHTUNG, WENN KURSWAHL NICHT MOEGLICH!!!
    		long GET_MATR_NR(void){ 
    			return MATR_NR;
    		}
    		string GET_NAME(void){ 
    			return NAME;
    		}
    };
    class BENUTZER;
    class KURS{ 
    	private:
    		string NAME;               // Kursname
    		int TEILN_ANZAHL;          // 3<=Teilnemheranzahl<=10
    		BENUTZER* TEILN_LISTE;  // Liste der Teilnehmer
    	public:
    		KURS(string NM); // Konstruktor: Name als Eigenschaft
    		int ERH_TEILN_ANZAHL(void); // Teilnehmer-Anzahl erhoehen
    		bool VORHANDEN(BENUTZER); // Schaut, ob Benutzer schon vorhanden
    		int AUFNEHMEN(BENUTZER); // Nimmt neuen Benutzer auf
    		string GET_NAME(void){
    			return NAME;
    		}
    		int GET_TEILN_ANZAHL(void){
    			return TEILN_ANZAHL;
    		}
    		BENUTZER GET_TEILN_LISTE(int a){
    			return TEILN_LISTE[a];
    		}
    };
    BENUTZER::BENUTZER(string NM, long MNR):NAME(NM), MATR_NR(MNR){ // Konstruktor-Methode für Klasse KURS
    	cout << "Neuer BENUTZER erzeugt !\n\n";
    }
    int BENUTZER::WAEHLE_KURS(KURS){ // Definition der METHODE 	"WAEHLE_KURS"
    	if(KURS.GET_TEILN_ANZAHL()<10){
    		KURS.AUFNEHMEN(BENUTZER);
    		BELEGT_KURS=KURS;
    		return 1;
    	}
    	return 0; // Kurs konnte nicht gewaehlt werden -> neu waehlen lassen!!!
    }
    KURS::KURS(string NM):NAME(NM){ // Konstruktor-Methode für Klasse KURS
    	TEILN_ANZAHL=0; // Beim Erzeugen gibt es 0 Teilnehmer
    
    	BENUTZER* TEILN_LISTE = new BENUTZER[10];
    	cout << "Neuer Kurs erzeugt !\n\n";
    }
    int KURS::ERH_TEILN_ANZAHL(void){ // Definition der METHODE 	"ERH_TEILN_ANZAHL"
    // TEILN_ANZAHL wird um 1 erhoeht, wenn noch keine 10 Teilnehmer da
    // gibt return 0 zurueck, wenn Erhoehung nicht mehr moeglich
    	if(TEILN_ANZAHL<10){
    		TEILN_ANZAHL++;
    		return 1;
    	}
    	return 0;
    }
    bool KURS::VORHANDEN(BENUTZER USER){ // Definition der METHODE "VORHANDEN"
    // Untersucht, ob die Matrikelnummer und der Name schon in der Kursliste steht
    // Wenn MART_NR UND(!) NAME identisch sind, wird sofort return 1 zurueckgegeben
    // die Funktion bricht dann ab und fuehrt return 0 nicht mehr aus.
    	int i;
    	for(i=0; i<TEILN_ANZAHL; i++){ 
    		if((TEILN_LISTE[i].GET_MATR_NR()==USER.GET_MATR_NR())&&(TEILN_LISTE[i].GET_NAME()==USER.GET_NAME()))
                    	return 1;
    	}
    	return 0;
    }
    int KURS::AUFNEHMEN(BENUTZER USER){ // Definition der METHODE 	"AUFNEHMEN"
    	if(TEILN_ANZAHL<10){
    		TEILN_LISTE[TEILN_ANZAHL]=USER;
            TEILN_ANZAHL++;
    		return 1;
    	}
    	return 0;
    }
    

    geht aber trotzdem net,

    'BENUTZER::BELEGT_KURS' verwendet undefiniertes class 'KURS'
    

    wie wendet man Standard-Container an, vector<KURS> liste; liste[0]=new KURS("blablubb"); usw 😕
    Ein Teilnehmer darf nur an einem Kurs teilnehmen 😉



  • ChrisB schrieb:

    Geht aber trotzdem net,

    'BENUTZER::BELEGT_KURS' verwendet undefiniertes class 'KURS'
    

    Benutzer enthält ein komplettes Objekt vom Typ Kurs - dafür ist die komplette Definition notwendig. Kurs hat nur einen Zeiger auf Benutzer, da reicht eine Forward-Deklaration.

    wie wendet man Standard-Container an, vector<KURS> liste; liste[0]=new KURS("blablubb"); usw 😕

    Fast:

    class Kurs
    {
      vector<Benutzer> teilnehmer;
    public:
      Kurs()
      {
        ...
      }
    
      anmelden(const Benutzer& neu)
      {
        teilnehmer.pus_back(neu);
      }
    };
    


  • Hab jetzt noch mehr Fehler als vorher :sad:

    1>..\LNcpp2\ln2-klein.cpp(44) : error C2027: Verwendung des undefinierten Typs "Benutzer"
    1>        ..\LNcpp2\ln2-klein.cpp(18): Siehe Deklaration von 'Benutzer'
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2228: Links von ".get_matr_nr" muss sich eine Klasse/Struktur/Union befinden.
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2027: Verwendung des undefinierten Typs "Benutzer"
    1>        ..\LNcpp2\ln2-klein.cpp(18): Siehe Deklaration von 'Benutzer'
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2228: Links von ".get_matr_nr" muss sich eine Klasse/Struktur/Union befinden.
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2027: Verwendung des undefinierten Typs "Benutzer"
    1>        ..\LNcpp2\ln2-klein.cpp(18): Siehe Deklaration von 'Benutzer'
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2228: Links von ".get_name" muss sich eine Klasse/Struktur/Union befinden.
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2027: Verwendung des undefinierten Typs "Benutzer"
    1>        ..\LNcpp2\ln2-klein.cpp(18): Siehe Deklaration von 'Benutzer'
    1>..\LNcpp2\ln2-klein.cpp(44) : error C2228: Links von ".get_name" muss sich eine Klasse/Struktur/Union befinden.
    1>..\LNcpp2\ln2-klein.cpp(60) : error C2027: Verwendung des undefinierten Typs "Benutzer"
    1>        ..\LNcpp2\ln2-klein.cpp(18): Siehe Deklaration von 'Benutzer'
    1>..\LNcpp2\ln2-klein.cpp(113) : error C2512: 'Kurs': Kein geeigneter Standardkonstruktor verfügbar
    1>..\LNcpp2\ln2-klein.cpp(132) : error C2662: 'Kurs::get_teiln_anzahl': this-Zeiger kann nicht von 'const Kurs' in 'Kurs &' konvertiert werden
    1>        Durch die Konvertierung gehen Qualifizierer verloren
    1>..\LNcpp2\ln2-klein.cpp(133) : error C2275: 'Benutzer': Ungültige Verwendung dieses Typs als Ausdruck
    1>..\LNcpp2\ln2-klein.cpp(176) : error C2512: 'Kurs': Kein geeigneter Standardkonstruktor verfügbar
    1>..\LNcpp2\ln2-klein.cpp(177) : error C2466: Zuordnung eines Arrays der konstanten Größe 0 nicht möglich.
    1>..\LNcpp2\ln2-klein.cpp(177) : error C2372: 'nr': Neudefinition; unterschiedliche Dereferenzierungstypen
    1>        ..\LNcpp2\ln2-klein.cpp(175): Siehe Deklaration von 'nr'
    1>..\LNcpp2\ln2-klein.cpp(177) : error C2075: 'nr': für die Initialisierung eines Arrays sind geschweifte Klammern erforderlich
    1>..\LNcpp2\ln2-klein.cpp(177) : error C2539: "new": "Kurs" ist kein Standardkonstruktor zur Initialisierung von Objektarrays.
    1>        ..\LNcpp2\ln2-klein.cpp(19): Siehe Deklaration von 'Kurs'
    1>..\LNcpp2\ln2-klein.cpp(178) : error C2372: 'nr': Neudefinition; unterschiedliche Dereferenzierungstypen
    1>        ..\LNcpp2\ln2-klein.cpp(175): Siehe Deklaration von 'nr'
    1>..\LNcpp2\ln2-klein.cpp(178) : error C2075: 'nr': für die Initialisierung eines Arrays sind geschweifte Klammern erforderlich
    1>..\LNcpp2\ln2-klein.cpp(178) : error C2539: "new": "Kurs" ist kein Standardkonstruktor zur Initialisierung von Objektarrays.
    1>        ..\LNcpp2\ln2-klein.cpp(19): Siehe Deklaration von 'Kurs'
    1>..\LNcpp2\ln2-klein.cpp(179) : error C2372: 'nr': Neudefinition; unterschiedliche Dereferenzierungstypen
    1>        ..\LNcpp2\ln2-klein.cpp(175): Siehe Deklaration von 'nr'
    1>..\LNcpp2\ln2-klein.cpp(179) : error C2075: 'nr': für die Initialisierung eines Arrays sind geschweifte Klammern erforderlich
    1>..\LNcpp2\ln2-klein.cpp(179) : error C2539: "new": "Kurs" ist kein Standardkonstruktor zur Initialisierung von Objektarrays.
    1>        ..\LNcpp2\ln2-klein.cpp(19): Siehe Deklaration von 'Kurs'
    1>..\LNcpp2\ln2-klein.cpp(223) : error C2360: Initialisierung von 'teilnehmer' durch 'case'-Marke übersprungen
    1>        ..\LNcpp2\ln2-klein.cpp(202): Siehe Deklaration von 'teilnehmer'
    1>..\LNcpp2\ln2-klein.cpp(243) : error C2361: Initialisierung von 'teilnehmer' durch 'default'-Marke übersprungen
    1>        ..\LNcpp2\ln2-klein.cpp(202): Siehe Deklaration von 'teilnehmer'
    1>Das Buildprotokoll wurde unter "file://d:\Users\Admin\Documents\Visual Studio 2005\Projects\InfoII\LNcpp2\ln2-klein\Debug\BuildLog.htm" gespeichert.
    1>ln2-klein - 25 Fehler, 0 Warnung(en)
    
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    class Benutzer;
    class Kurs{ 
    	private:
    		string name;               // Kursname
    		int teiln_anzahl;          // 3<=teilnemheranzahl<=10
    		//Benutzer* teiln_liste;  // liste der teilnehmer
    		vector<Benutzer> teiln_liste;
    	public:
    		Kurs(string NM){ // Konstruktor: name als Eigenschaft
    			name=NM;
    			teiln_anzahl=0; // Beim Erzeugen gibt es 0 teilnehmer
    			cout << "Neuer Kurs erzeugt !\n\n";
    		}
    		//~Kurs(); // Destruktor
    		int ERH_teiln_anzahl(void){ // teilnehmer-anzahl erhoehen
    // teiln_anzahl wird um 1 erhoeht, wenn noch keine 10 teilnehmer da
    // gibt return 0 zurueck, wenn Erhoehung nicht mehr moeglich
    			if(teiln_anzahl<10){
    				teiln_anzahl++;
    				return 1;
    			}
    			return 0;
    		}
    		bool vorhanden(Benutzer user){ // Schaut, ob Benutzer schon vorhanden
    			int i;
    			for(i=0; i<teiln_anzahl; i++){ 
    			if((teiln_liste.at(i).get_matr_nr()==user.get_matr_nr())&&(teiln_liste.at(i).get_name()==user.get_name()))
    				return 1;
    			}
    			return 0;
    		}
    		int aufnehmen(const Benutzer& neu){ // Nimmt neuen Benutzer auf
    			if(teiln_anzahl<10){
    				//[teiln_anzahl]=user;
    				teiln_liste.push_back(neu);
    				teiln_anzahl++;
    				return 1;
    			}
    			return 0;
    		}
    		string get_name(void){		return name;}
    		int get_teiln_anzahl(void){		return teiln_anzahl;}
    		Benutzer get_teiln_liste(int a){		return teiln_liste.at(a);}
    };
    class Benutzer{ 
    	private:
    		string name;            // name
    		long matr_nr;           // Matrikelnummer
    		Kurs belegt_Kurs;       // Kurs, der belegt werden soll
    	public:
    		Benutzer(string NM, long Mnr){ // Konstruktor: name und Matr.nr. als Eigenschaft,
    		// gewuenschter Kurs wird ueber eigene Methode gesetzt, 
    			name=NM;
    			matr_nr=Mnr;
    			cout << "Neuer Benutzer erzeugt !\n\n";
    		}
    		//~Benutzer(); // Destruktor
    		int waehle_Kurs(const Kurs KRS){ // ACHTUNG, WENN KursWAHL NICHT MOEGLICH!!!
    			if(KRS.get_teiln_anzahl()<10){
    				KRS.aufnehmen(Benutzer);
    				belegt_Kurs=(Kurs)KRS;
    				return 1;
    			}
    			return 0; // Kurs konnte nicht gewaehlt werden -> neu waehlen lassen!!!
    		}
    		long get_matr_nr(void){ 
    			return matr_nr;
    		}
    		string get_name(void){ 
    			return name;
    		}
    };
    ...
    

    Mein Bett ruft. Vielleicht hab ich morgen mehr Ideen 😉


  • Mod

    Du kannst in einer Klasse keine Instanz ihrer selbst haben. Wie sollte das gehen? Und was soll das bringen?

    P.S.: Jetzt kann ich schon meine Antworten im Minutentakt recyclen:
    http://www.c-plusplus.net/forum/p2077719#2077719



  • Hm, stimmt. Irgendwie komisch 🙄 Danke!



  • Den Fehler

    SeppJ schrieb:

    Du kannst in einer Klasse keine Instanz ihrer selbst haben.

    hab ich ausgebessert, komm aber nie unter 18 Fehler und mach bezüglich des Attributs KURS in der Klasse BENUTZER etwas was ich sonst net mach: Aufgeben. Hab KURS durch ne int ersetzt.
    Mein neues Problem scheint der Umgang mit einem Vector zu sein:

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    class Benutzer{
    	private:
    		string name;            // name
    		long matr_nr;           // Matrikelnummer
    		int belegt_KursNr;       // Kurs, der belegt werden soll
    	public:
    		Benutzer(string NM, long Mnr){ 
    			name=NM;
    			matr_nr=Mnr;
    		}
    };
    main(){
           char a, b;
           int c;
           Benutzer dummy=new Benutzer("dummy", 42);
           vector<Benutzer> teiln_liste(); // Soll ein Feld von Benutzern geben
           a='c';
           for(c=0; c<10; c++) //Belegung
                    //teiln_liste[c]=&dummy;       //?????
                    teiln_liste.push_back(dummy);       //?????
           for(c=0; c<10; c++){//Ausgabe
                    tmp=teiln_liste[c].get_name();
                    cout << tmp << "\n";
                    }
           system("pause");
    }
    


  • Benutzer dummy=new Benutzer("dummy", 42);
    

    So läuft das nicht. Richtig wäre:

    Benutzer dummy("dummy", 42);
    

    Ausserdem solltest du alle Membervariablen initialisieren, und dazu die Konstruktor-Initialisierungsliste verwenden.



  • also ist das problem (ich hab zufällig gerade dasselbe problemchen gehabt), dass man 2 klassen hat, die sich gegenseitig als member haben. ergo würde daraus wie bei einer klasse die sich selsbt als member hat, folgen, dass sie sich rekursiv beinhalten und so ihre größe theoretisch ins unendliche wachsen würde. aber genau diese zyklische abhängigkeit unterbindet der compiler und spuckt den fehler C2079 (Microsoft Visual C++ 2010 Pro)
    Bsp:

    class A;
    class B;
    
    class A{
        B b;
    };
    class B {
        A a;
    };
    
    int main()
    {
        A crasher;
        return 0x0;
    }
    

    entfernen kann man das problem indem man zum einen anders designt(einfache aussage) oder einen der beiden als pointer (smart pointer ist auch ok) in die andere klasse setzt...
    Bsp:

    class A;
    class B;
    
    class A{
        B b;
    };
    class B {
        std::shared_pointer<A> a;
    };
    
    int main()
    {
        A crasher;
        return 0x0;
    }
    

    nachteil ist hier halt, dass man dereferenzieren muss bei jedem zugriff...



  • Eine normale einfache Liste kann ich inzwischen machen:

    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    class Benutzer
    {
    private:
    	string name;            // name
    	long matr_nr;           // Matrikelnummer
    	int kursNr;		// Kurs, der belegt werden soll
    public:
    	Benutzer(const string& nname, const long mmatr_nr, const int kkursNr)
    	:name(nname), matr_nr(mmatr_nr), kursNr(kkursNr){}
    	void set_name(const string& nname){name = nname;} //z.B. fuer spaetere Namensaenderung
    	void set_matr_nr(const long mmatr_nr){matr_nr=mmatr_nr;}
    	void set_kursNr(const int kkursNr){kursNr=kkursNr;}
    	string get_name(void){return name;}
    	long get_matr_nr(void){return matr_nr;}
    	long get_kursNr(void){return kursNr;}
    };
    // neuen Datentypen definieren
    typedef vector<Benutzer> BenutzerListe;
    string tmp;
    int main(){
    	BenutzerListe alleBenutzer;
    	Benutzer student("Eins", 13, 1);
    	alleBenutzer.push_back(student);
    	/*
    	Benutzerliste studenten;
    	studenten.push_back(const new Benutzer("zwei", 14));
    	alleBenutzer.push_back(studenten[1]);
    	*/
    	for(unsigned long i = 0; i < alleBenutzer.size(); ++i)
    		cout << (alleBenutzer[i]).get_name() << (alleBenutzer[i]).get_matr_nr() << endl;
    	system("pause");
    	return 0;
    }
    

    Jetzt möcht ich aber mehr als einen Benutzer erzeugen, also wieder ein Vektor??? aber wie? Den alten Benutzer löschen und nochmal verwenden klappt auch net:(



  • Wie sehen denn die Beziehungen zwischen Kursen und Benutzern aus, das ist doch mit Sicherheit eine M:N Beziehung, oder nicht? Kannst du das nicht so modellieren?

    class Kurs;
    class Benutzer;
    
    typedef shared_pt<Kurs> KursPtr;
    typedef shared_ptr<Benutzer> BenutzerPtr;
    
    class Kurs
    {
       friend void belege_kurs( BenutzerPtr& b, KursPtr& k );
    
       ...
       std::vector<BenutzerPtr> Teilnehmer_;
    
       void schreibe_ein( const BenutzerPtr& b )
       {
          // TO DO: Duplikate prüfen
          Teilnehmer_.push_back( b );
       }
       ...
    };
    
    class Benutzer
    {
       friend void belege_kurs( BenutzerPtr& b, KursPtr& k );
       ...
       std::vector<KursPtr> Kurse_;
       ...
    
       void nimm_teil( const KursPtr& k )
       {
          // TO DO: Duplikate prüfen
          Kurse_.push_back( k );
       }
    };
    
    void belege_kurs( BenutzerPtr& b, KursPtr& k )
    {
       b->nimm_teil( k );
       k->schreibe_ein( b );
    }
    


  • Also, Danke für eure Hilfe! 👍
    Verwende jetzt

    Benutzer student[n];
    student[studNr].NewBenutzer(name, mtrnr);
    

    weil ein normaler Konstruktor nicht bei Arrays funktioniert, d.h.

    Benutzer student[studNr](name, mtrnr);
    

    geht eben leider net.
    Scheint momentan zu laufen, glaub ich kriegs jetzt hin 🙂


Anmelden zum Antworten