Eingabe eines Strings bei dynamischen Objekt



  • Hallo zusammen,

    mein erster Beitrag und gleich ein Problem 😃

    Und zwar folgendes, ich habe eine Klasse und möchte ein Attribut eingeben. Die Instanzen der Klasse werden dynamisch erzeugt. Eine Stringeingabe funktioniert aber nicht. Wenn die Instanz statisch erzeugt wird allerdings schon.

    Hier mal der Code aufs minimale reduziert

    #include <iostream>
    #include <cstdlib>
    #include <string>
    
    using namespace std;
    
    class PRODUKT
    {
        private:
            string name;
        public:
            void set_name(){cout << "Bitte Namen eingeben: "; cin>>name;}   //auch mit getline(cin, name); getestet
    };
    
    int main()
    {
        PRODUKT X;
        X.set_name();   //funktioniert
    
        PRODUKT* P;
        P->set_gruppe();    //hier stürzt das Programm ab
    
        system("PAUSE");
        return 1;
    }
    

    Ich hoffe mal, ihr könnt mir helfen 😮



  • PRODUKT* P = new PRODUKT; // Es ist immer schön, ein Objekt zu haben.



  • In deiner markierten Quelltextzeile greifst du an eine zufällige Stelle im Arbeitsspeicher zu. Das mag dein Betriebssystem aber nicht und lässt das Programm abstürzen.
    Du musst erst mit new eine Instanz erzeugen. Aber nicht vergessen, zu jedem new gehört auch ein delete. Oder du verwendest unique_ptr.



  • Ach klar... vielen Dank 😃
    Dann hab ich noch ein zweites Problem, und zwar möchte ich es als dynamisches Array haben (nicht Liste)

    PRODUKT *P[30];
        P[0] = new PRODUKT;
    

    Ist das so richtig? Also die Anzahl der Instanzen wird natürlich kontrolliert



  • realshadow schrieb:

    Ach klar... vielen Dank 😃
    Dann hab ich noch ein zweites Problem, und zwar möchte ich es als dynamisches Array haben (nicht Liste)

    std::vector<PRODUKT> container;
    // oder falls du unbedingt Pointer brauchst, was du nur brauchst wenn Polymorphie im Spiel ist:
    std::vector<std::unique_ptr<Product>> container;
    

    Und wieso UPPERCASE?


  • Mod

    Du hast kein Objekt erzeugt, sondern nur einen Zeiger da drauf. Der Zeiger zeigt irgendwo ins Nirvana, wenn du den dereferenzierst, stuerzt das Programm daher ab.

    Problem ist hier weniger die Stringeingabe, sondern, wie man in C++ dynamisch Objekte erzeugt. Das normale Vorgehen waere hier, die Objekte in einer Containerklasse wie std::vector (es gibt noch viele andere) zu packen, dann loest sich das Problem ganz von alleine. Wenn es etwas spezieller wird, dann ist eventuell auch einer der smart_pointer aus der Standardbibliothek und die Objekterzeugung dann mittels new (oder besser: make_shared/make_unique). Ein Smartpointer ist aber vermutlich eher nicht das, was du brauchst, ich wollte es bloss erwaehnen.

    Damit bewaffnet, sollten sich deine Probleme von alleine loesen.

    Noch ein Kritikpunkt: Dein Klassendesign ist nicht so toll. Separation of concerns wird verletzt. Ein Produkt hat sich nicht darum zu kuemmern, wie es einen Namen bekommt. Es hat einen Namen, den muss es sich nicht besorgen, den bekommt es. Und zwar bei der Erstellung, es sei denn, es kann auch sinnvolle Produkte ohne Namen geben. Jedenfalls hat ein Objekt nach seiner Erstellung voll einsatzfaehig zu sein und nicht weiterer Initialisierungsfunktionen zu beduerfen (die koennten naemlich vergessen werden). Es mag ein paar ganz spezielle Ausnahmen geben, aber das liegt hier sicherlich nicht vor. Verpass deinem Produkt einen Konstruktor, ueber den es seinen Namen erhaelt.

    edit: Viel zu langsam...



  • SeppJ schrieb:

    Noch ein Kritikpunkt: Dein Klassendesign ist nicht so toll. Separation of concerns wird verletzt. Ein Produkt hat sich nicht darum zu kuemmern, wie es einen Namen bekommt. Es hat einen Namen, den muss es sich nicht besorgen, den bekommt es. Und zwar bei der Erstellung, es sei denn, es kann auch sinnvolle Produkte ohne Namen geben. Jedenfalls hat ein Objekt nach seiner Erstellung voll einsatzfaehig zu sein und nicht weiterer Initialisierungsfunktionen zu beduerfen (die koennten naemlich vergessen werden). Es mag ein paar ganz spezielle Ausnahmen geben, aber das liegt hier sicherlich nicht vor. Verpass deinem Produkt einen Konstruktor, ueber den es seinen Namen erhaelt.

    edit: Viel zu langsam...

    Konstruktor ist vorhanden, hab ich nur rausgekürzt 😉

    Wenn es für alle Felder des Arrays ein new PRODUCT gibt, ist es dann nicht möglich?



  • realshadow schrieb:

    Wenn es für alle Felder des Arrays ein new PRODUCT gibt, ist es dann nicht möglich?

    Was ist dann nicht möglich?



  • Wenn es für alle Felder des Arrays ein new PRODUCT gibt, ist es dann möglich?

    Also ob es dann funktioniert?

    Also ich brauche maximal 30 dynamisch erzeugte Instanzen, muss auf jede Zugreifen und doppelt verkettete Listen kann ich noch nicht 😃



  • Wenn du max. 30 dynamische Objekte willst, machst du es so:

    PRODUKT *P = new PRODUKT[30];
    //...
    delete[] p;
    

    wenn du sowas brauchst, ist aber Nathans Lösung die richtige.



  • out schrieb:

    Wenn du max. 30 dynamische Objekte willst, machst du es so:

    PRODUKT *P = new PRODUKT[30];
    //...
    delete[] p;
    

    wenn du sowas brauchst, ist aber Nathans Lösung die richtige.

    Danke, wieso muss ich dann aber mit P[x].set_name() zugreifen und nicht mehr P[x]->set_name()? Bei Zeigern muss man doch per -> zugreifen?
    Das ist auch bei

    Produkt *P[30];
    P[1]=new PRODUKT;
    P[1]->set_name();
    

    Also ich habs zumindest so gelernt, bei Zeigern auf Objekte, immer mit -> auf Methoden zugreifen



  • "->" musst du nehmen, wenn sich links davon ein Zeiger auf ein Objekt befindet. "." nimmst du, wenn sich links davon ein Objekt befindet. "[]" bewirkt eine Dereferenzierung. Wenn du nun den Zeiger dereferenzierst, landest du bei einem PRODUKT-Objekt, also steht links ein Objekt, also muss der "." her.

    Ja, anders sieht es aus, wenn du jedes Objekt einzlen dynamisch erzeugst. Dann hast du 30 Zeiger und 30 Objekte. Wenn du hier dann den "[]" anwendest, landest du nicht sofort bei einem Objekt, sondern erst bei einem Zeiger, darum brauchst du "->".

    Also in dem einen Fall hast du 30 Zeiger und 30 Objekte, in dem anderen Fal hast du 1 Zeiger und 30 Objeke.



  • out schrieb:

    "->" musst du nehmen, wenn sich links davon ein Zeiger auf ein Objekt befindet. "." nimmst du, wenn sich links davon ein Objekt befindet. "[]" bewirkt eine Dereferenzierung. Wenn du nun den Zeiger dereferenzierst, landest du bei einem PRODUKT-Objekt, also steht links ein Objekt, also muss der "." her.

    Ja, anders sieht es aus, wenn du jedes Objekt einzlen dynamisch erzeugst. Dann hast du 30 Zeiger und 30 Objekte. Wenn du hier dann den "[]" anwendest, landest du nicht sofort bei einem Objekt, sondern erst bei einem Zeiger, darum brauchst du "->".

    Also in dem einen Fall hast du 30 Zeiger und 30 Objekte, in dem anderen Fal hast du 1 Zeiger und 30 Objeke.

    Alles klar - vielen Dank!

    ist mit PRODUKT *P = new PRODUKT[30]; die Instanzierung dann noch dynamisch?



  • Vielleicht sollte man auch noch folgendes klarstellen:

    new PRODUKT[30]
    

    Bedeutet: Array von 30 PRODUKT-Objekten im dynamischen Speicher.

    PRODUKT *P[30];
    

    Bedeutet: Array von 30 PRODUKT-Zeigern im automatischen Speicher.



  • OK, danke!


  • Mod

    Warum wird hier new fuer Felder empfohlen? Denkt nicht mal einer an die Kinder vector?



  • SeppJ schrieb:

    Warum wird hier new fuer Felder empfohlen? Denkt nicht mal einer an die Kinder vector?

    Ihm wurde gesagt, dass Nathans Lösung der richtige Weg ist. Darauf ist er aber nicht eingegangen. Ich denke, es handelt sich hier um "mach es so wie dein Lehrer es macht".


Log in to reply