Array von Klassen initialisieren



  • Nexus schrieb:

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

    Weil sein Auto keinen Standardkonstruktor hat.



  • Nexus schrieb:

    Auto MeineAutos[5];
    MeineAutos[0].Auto(4, 6); // oder
    MeineAutos[1] = Auto(0, 2);
    

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

    Wobei ich eh statt einem Array zu einem Vector greifen würde:

    #include <vector>
    //...
    std::vector<Auto> autos;
    autos.push_back(Auto(4, 6));
    autos.push_back(Auto(0, 2));
    // ...
    


  • Danke Velo, aber es funktioniert nicht richtig:

    autos **a = new autos[2];
    
    a[0] = new autos(4,6);
    a[1] = new autos(8,8);
    

    So hab ich das jetzt, Fehlermeldungen für jede Variable in der Klasse!

    request for member blablabla, which is of non-class type ‘autos*’
    
    //UND beim initialisieren:
    
    main.cc:84: error: cannot convert ‘autos*’ to ‘autos**’ in initialization
    main.cc:86: error: expected constructor, destructor, or type conversion before ‘=’ token
    

    Was mache ich falsch?



  • P.S: Alternative ist z.B. boost::ptr_vector<Auto> [Siehe auch Boost, Pointer Container]



  • 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?


Anmelden zum Antworten