Array von Klassen initialisieren



  • ok hab jetzt den vorschlag mit vektor ausprobiert, Der fehler mit
    "request for member..." ist jetzt weg, aber
    beim push_backen gibt er mir aus:

    main.cc:90: error: expected constructor, destructor, or type conversion before ‘.’ token
    main.cc:9
    


  • autos** a ist ein Pointer auf Pointer auf autos. du kannst einem Pointerpointer kein Objekt zuweisen, nur einem Klassenpointer...still with me? 😉

    Du müsstest also a ein Array aus Pointern zuweisen:

    a = new autos*[4];
    autos[0] = new autos;
    autos[1] = new autos;
    .
    .
    .



  • Autonom schrieb:

    Danke Velo, aber es funktioniert nicht richtig

    komisch, bei mir gehts 😉

    #include <iostream>
    using namespace std;
    
    class Auto
    {
    public:
    	Auto(size_t alter, size_t anzSitze);
    
        size_t zeigeAlter() const;
        size_t zeigeAnzahlSitze() const;
    
    private:
        size_t m_alter, m_anzSitze;
    };
    
    //Implementierung
    
    Auto::Auto(size_t alter, size_t anzSitze)
    : m_alter(alter), m_anzSitze(anzSitze)
    {
    }
    
    size_t Auto::zeigeAlter() const
    {
        return m_alter;
    }
    
    size_t Auto::zeigeAnzahlSitze() const
    {
        return m_anzSitze;
    }
    
    //Hauptteil
    
    int main()
    {
        const int ANZAHL = 5;
    
        //erstellen
        Auto **autos = new Auto*[ANZAHL];
        autos[0] = new Auto(4,6);
        autos[1] = new Auto(0,2);
        //...
    
        cout << "Das erste Auto ist " << autos[0]->zeigeAlter() << " Jahre alt.\n";
        cout << "Das zweite Auto hat " << autos[1]->zeigeAnzahlSitze() << " Sitze." << endl;
    
        //verschrotten
        for(size_t i = 0; i < ANZAHL; ++i)
            delete autos[i];
        delete [] autos;
    }
    


  • asc@ausgeloggt schrieb:

    Nein. Variante 1 bitte nicht benutzen! (Unzulässig)
    Man darf den Konstruktor eines Objektes nicht nachträglich aufrufen.

    Tut mir leid, dass ich hier Unsinn verbreite. Ich selber benutze eigentlich (wenn ich überhaupt in eine solche Situation komme) auch die Zuweisung, aber ich dachte, das andere wäre legitim. Danke für die Berichtigung!

    Und einigen wir uns darauf, mit std::vector geht das definitiv am einfachsten 😉

    velo schrieb:

    Nexus schrieb:

    Warum machst du es mit Zeigern, sogar das Array ist auf dem Heap?

    Weil sein Auto keinen Standardkonstruktor hat.

    Du meinst, keinen spezifischen Standardkonstruktor, der die Membervariabeln initialisiert. Wenn kein eigener implementiert wurde, wird ein Standardkonstruktor vom Compiler erstellt.

    An der Stelle fände ich die Implementation eines Standardkonstruktors aber wesentlich einfacher und auch zukunftssicherer als ein Zeigerarray aus Zeigern.



  • 1. Vektor wäre mir lieber als Array (wäre aber auch damit zufrieden)

    ich hab's jetzt mit Vektor probiert, genauso wie es asc vorgeschlagen hat, wie gesagt, er packt den push_back nicht.

    Kann es sein, dass

    std::vector<Auto> autos;
    

    falsch ist?



  • Autonom schrieb:

    Kann es sein, dass

    std::vector<Auto> autos;
    

    falsch ist?

    Diese Zeile ist schon richtig, aber könntest du mal den ganzen Code inklusive Fehlermeldungen zeigen? Hast du <vector> inkludiert?



  • Der ganze Code wäre viel zu riesig, aber alle relevanten Teile:

    //main
    #include <vector>
    #include <iostream>
    #inlcude <autos.h>
    
    using namespace std;
    
    vector<autos> a;
    a.push_back(autos(4, 6));
    a.push_back(autos(0, 2));
    
    //autos.h
    
    #ifndef _AUTOS_
    
    #define _AUTOS_
    
    class autos
    
    {
    
    public:
    
    	autos(int alter, int sitze);
    
    private:
            int alter;
            int sitze;
    };
    
    #endif
    


  • Hmmmm .... jetzt wären noch hilfreich:
    - die Fehlermeldung
    - soll "a" ein globales Objekt sein ? Befinden sich die a.push_back()-Anweisungen innerhalb einer Funktion (z.B. main()) ?

    BTW: autos ist ein wenig irreführend.... (wenn auch nur eine Kleinigkeit)

    Gruß,

    Simon2.



  • Autonom schrieb:

    #inlcude <autos.h> // Schreibfehler...
    
    vector<autos> a;
    a.push_back(autos(4, 6));  // ist das alles in der main()-Funktion?
    a.push_back(autos(0, 2));  // Global darfst du das nämlich nicht machen
    

    Und wie stehts mit deiner Klasse? Ist der Standardkonstruktor irgendwo definiert?


  • Mod

    Nexus schrieb:

    velo schrieb:

    Nexus schrieb:

    Warum machst du es mit Zeigern, sogar das Array ist auf dem Heap?

    Weil sein Auto keinen Standardkonstruktor hat.

    Du meinst, keinen spezifischen Standardkonstruktor, der die Membervariabeln initialisiert. Wenn kein eigener implementiert wurde, wird ein Standardkonstruktor vom Compiler erstellt.

    Nur wenn kein anderer Konstruktor vom Nutzer deklariert wurde. Da aber nach Voraussetzung ein Konstruktor mit zwei Argumenten existiert, und der offensichtlich nicht vom Compiler stammen kann, wird der Compiler keinen Defaultkonstruktor deklarieren.
    Ein Array-new-Ausdruck kann keinen spezifischen Kosntruktor aufrufen, lediglich wenn der betreffende Typ ein POD ist (hier nicht der Fall), besteht die Wahl zwischen Value-Initialisierung bzw. keiner Initialisierung. Ein statisches oder automatisches Array kann dagegen über eine Aggregatinitialisierungsliste initialisiert werden. Standardkontainer erlauben dagegen erheblich größere Freiheiten bei der Initialisierung.



  • - (überflüssig) -



  • wie lautet denn die aktuelle fehlermeldung?
    der code, den du gepostet hast, sieht bis auf den typo mit include richtig aus. ich nehme an, du hast den vector kram in der main funktion? push_back kann natürlich, ebenso wie andere funktionen und methoden, nur in einer funktion oder methode aufgerufen werden.

    mithilfe von boost::assign kann man vectoren und andere standardkonforme container übrigens sehr elegant initialisieren:

    #include "Auto.h"
    
    #include <iostream>
    #include <vector>
    #include <boost/assign.hpp>
    using namespace std;
    using namespace boost::assign;
    
    int main()
    {
        vector<Auto> autos;
        autos += Auto(4, 6), Auto(0,2);
    
        cout << "Das erste Auto ist " << autos[0].zeigeAlter() << " Jahre alt.\n";
        cout << "Das zweite Auto hat " << autos[1].zeigeAnzahlSitze() << " Sitze." << endl;
    }
    


  • OK!

    Global war das Problem!

    Nun aber weiter - warum nur global?

    Ich nutze die Klasse in vielen Funktionen, die ich in der main.cpp habe, wie mach ich das dann? jedes mal als übergabeparameter den vektor übergeben?

    (aufgrund nicht mehr global hab ich jetzt natürlich errors: not deklared in this scope -> muss ich also wohl übergeben)



  • ah ok, jetzt ist mir klar warum push_back global nicht möglich ist - und dennoch, wie löse ich das am elegantesten, wenn ich in irgend einer funktion etwas von den autos brauche?

    sprich:

    void readout(/*hier vektor übergeben?*/)
    for(int i=0; i<o.size(); i++)
    {
       cout << o.radanzahl << endl
    }
    


  • Die Deklaration darf global sein, die Initialisierung der einzelnen Elemente (bzw. die Anhänge-Funktion push_back()) muss in einer Funktion stehen.
    Alternativ machst deklarierst du den Vektor auch lokal und übergibst ihn.

    std::vector autos;       // Deklaration global
    
    int main()
    {
       autos.push_back(...); // Anhängung von Elementen
       funktion();           // keine Übergabe erforderlich, da autos global ist
    }
    

    oder:

    int main()
    {
       std::vector autos;    // Deklaration lokal
       autos.push_back(...); // Anhängung von Elementen
       funktion(autos);      // Übergabe des Vektors als Parameter              
    }
    

    @ Simon2
    Da du natürlich die Beweismittel vernichtet hast, kann ich dich nicht mehr zitieren 😉
    Aber du hast geschrieben, der Kopierkonstruktor werde auch nicht mehr automatisch vom Compiler erstellt, wenn irgendein Konstruktor selber implementiert wurde. Das ist jedoch falsch. Er wird nur nicht mehr erstellt, wenn ein eigener Kopierkonstruktor vorhanden ist.
    Beim Standardkonstruktor gebe ich dir recht, ich war bis jetzt der Ansicht, das würde immer vom Compiler gemacht, wenn kein eigener implementiert war.

    Ich merke eben, ich kenne mich diesbezüglich zu wenig aus, weil ich für eine Klasse sowieso immer den Standardkonstruktor selber schreibe (nur schon damit die Membervariable nicht irgendwelche Werte annehmen).



  • puh, gut dass es global geht, ansonsten wäre das für mich ein weltuntergang gewesen. Danke!

    ich glaube somit war's das!

    Danke vielvielmals!

    Damit werd ich mich auch hier im Forum registrieren, super board, gut, dass man auch ohne Anmelden posten kann, jetzt bin ich überzeugt.

    Danke!

    By the way:

    Was ist boost? was kann man damit alles machen?



  • global ist hässlich. du könntest stattdessen eine garage bauen:

    #include <iostream>
    #include <vector>
    #include <boost/assign.hpp>
    using namespace std;
    using namespace boost::assign;
    
    //Auto
    
    class Auto
    {
    public:
    	Auto(size_t alter, size_t anzSitze);
    
        size_t zeigeAlter() const;
        size_t zeigeAnzahlSitze() const;
    
    private:
        size_t m_alter, m_anzSitze;
    };
    
    //Auto Implementierung
    
    Auto::Auto(size_t alter, size_t anzSitze)
    : m_alter(alter), m_anzSitze(anzSitze)
    {
    }
    
    size_t Auto::zeigeAlter() const
    {
        return m_alter;
    }
    
    size_t Auto::zeigeAnzahlSitze() const
    {
        return m_anzSitze;
    }
    
    //Garage
    
    class Garage
    {
    public:
    	static Garage &Aufmachen();
    
        const Auto &zeigeAuto(size_t position) const;
    
    private:
    	Garage();
    
    	vector<Auto> m_autos;
    };
    
    //Garage Implementierung
    
    Garage::Garage()
    {
        m_autos += Auto(4, 6), Auto(0,2); //eventuell mehr Autos in die Garage tun
    }
    
    Garage &Garage::Aufmachen()
    {
        static Garage g;
        return g;
    }
    
    const Auto &Garage::zeigeAuto(size_t position) const
    {
        return m_autos[position];
    }
    
    //Funktionen die Autos aus der Garage brauchen
    
    void foo()
    {
        cout << "Das erste Auto ist "
            << Garage::Aufmachen().zeigeAuto(0).zeigeAlter()
            << " Jahre alt.\n";
    }
    
    void bar()
    {
        Garage &g = Garage::Aufmachen();
    
        cout << "Das zweite Auto hat "
            << g.zeigeAuto(1).zeigeAnzahlSitze()
            << " Sitze." << endl;
    }
    
    //Hauptteil
    
    int main()
    {
        foo();
        bar();
    }
    

    boost hat sehr viele und sehr gute ergänzungen zu den c++ bibliotheken. es ist kostenlos und wird von unternehmen wie adobe verwendet. die meisten sachen aus boost kann man direkt verwenden, indem man sie inkludiert.



  • Autonom schrieb:

    By the way:
    Was ist boost? was kann man damit alles machen?

    Boost ist eine mächtige C++ Bibliothekssammlung (ich vermeide absichtlich die einzahl), die frei erhältlich ist. In der Regel braucht man nicht alles von Boost, sondern wählt aus einzelnen Bibliotheken das für sich sinnvolle aus.

    Ich würde sagen Boost ist nach der C++Standardbibliothek die zweit wichtigste C++ Bibliothek(-ssammlung). Die Boostautoren sitzen teilweise auch in Standardkomitee und Teile von Boost werden auch in den kommenden C++ Standard (C++0x) übernommen.

    Je nach Compiler gibt es ggf. installierbare Packete (so für MSVC 2003 und 2005 wenn ich mich nicht irre), ansonsten bitte die Anleitung beachten. Wobei das linken nicht bei allen Bibliotheken nötig ist (so sind z.B. die Smartpointer eine reine Header-Bibliothek).

    cu André



  • achso, ich hätte vllt noch dazu schreiben sollen, dass mit Garage::Aufmachen immer auf ein und die selbe garage zugegriffen wird. dies funktioniert gemäß des entwurfsmusters singleton. man braucht also keine angst zu haben, dass die garage mitsamt den autos bei jedem zugriff erstellt wird, denn dies passiert nur beim ersten mal und anschließend wird lediglich der zugriff auf die vorhandene garage geöffnet. wenn man nicht möchte, dass die garage die ganze zeit da (im speicher) ist, kann man dies wie folgt tun:

    //Garage
    
    class Garage
    {
    public:
    	static Garage &Aufmachen();
    
    	//wenn die Garage nicht mehr benötigt wird,
    	//kann hiermit der Spiecher freigegeben werden
    	static void Abreissen();
    
        const Auto &zeigeAuto(size_t position) const;
    
    private:
    	Garage();
    
    	//der Kopierkonstruktor sollte auch geschützt werden,
    	//um zuweisungen zu verhindern
    	Garage(const Garage &g){} 
    
    	vector<Auto> m_autos;
    
    	//statischer Zeiger auf die einzige Garage
    	static Garage *m_dieGarage;
    };
    
    //Garage Implementierung
    
    Garage *Garage::m_dieGarage = 0;
    
    Garage::Garage()
    {
        m_autos += Auto(4, 6), Auto(0,2); //eventuell mehr Autos in die Garage tun
    }
    
    Garage &Garage::Aufmachen()
    {
        if (m_dieGarage == 0)
            m_dieGarage = new Garage;
        return *m_dieGarage;
    }
    
    void Garage::Abreissen()
    {
        delete m_dieGarage;
        m_dieGarage = 0;
    }
    
    const Auto &Garage::zeigeAuto(size_t position) const
    {
        return m_autos[position];
    }
    


  • Hi, sorry das ich das nocheinmal aufrolle. Aber das Beispiel und die erklärung von velo sind spitze 🙂

    ich versuche mir aus lerngründe soviele Beispiele wie möchlich, um das Thema vectoren zusammen zu holen.

    Jetzt hätte ich beim Beispiel von | velo | versucht, Dynamisch das vector array zu erweitern, bin aber leider noch gescheitert.
    Im testfall sollte im main nach dem aufruf von foo und bar - mit einem pushback ein weiteres Element hinzugefügt werden das danach wieder ausgegen werden sollt.

    Frage ist das so überhaupt möglich?
    Könnte mir sonst evtl jemand einen Tipp geben, würde es gerne weiter probieren, sofern überhaupt möglich.

    Danke


Anmelden zum Antworten