Klasseninstanz über std::vector erzeugen



  • Hallo,
    ich versuche gerade die Fehlermeldung:
    "no matching member functiion for call to 'push_back' nachzuvollziehen.

    in diesem Fall tritt sie auf:

    vector<int>Liste(0);
    Liste.push_back();  //no matching member functiion for call to 'push_back'
    

    so wird sie beseitigt, weil der Funktion push_back ein int Wert übergeben wird.

    vector<int>Liste(0);
    Liste.push_back(1);
    

    Ich versuche das jetzt jedoch anstelle von int Werten mit Klasseninstanzen.
    Das Problem:
    Die Variablen sind private und es gibt Zugriffsfunktionen.
    Nennen wir die Klasse einmal "punkt".
    Dann kann weder auf diese Weise:

    vector<punkt>Liste(0);
    Liste.push_back();  //no matching member functiion for call to 'push_back'
    

    Noch auf diese Weise:

    vector<punkt>Liste(0);
    Liste.push_back(punkt);  //'punkt' does no refer to a value
    

    eine neue Klasseninstanz erzeugt werden.

    Weis jemand wie hier die Lösung aussieht?



  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    punkt

    Zeig mal "punkt".
    Wenn das Ding einen Konstruktor hat, der nicht leer ist, musst du natürlich den Konstruktor natürlich auch so aufrufen.

    Und leere Konstruktoren musst du dann so aufrufen:

    punkt()
    

    Bzw. wenn du einen leeren Konstruktor hast, kannst du auch mit "resize" einfach Objekte im vector erzeugen.



  • So erzeugst du ja auch keine neue Klasseninstanz, es fehlen die Klammern:

    vector<punkt>Liste(0);
    Liste.push_back(punkt()); 
    

    Oder mittels einer Variablen:

    vector<punkt>Liste(0);
    punkt p;
    Liste.push_back(p); 
    


  • Vielen Dank!🙂

    Hier ist punkt.h:

    #ifndef PUNKT_H
    #define PUNKT_H
    
    class punkt
    {
    private:
        int x,y;
    
    public:
        punkt();
        void setPunkt();
        void getPunkt();
    };
    
    #endif // PUNKT_H
    

    Vorzugsweise würde ich es dann so machen:

    Liste.push_back(punkt());
    Liste[1].setPunkt();
    

    weil ja so:

    vector<punkt>Liste(0);
    punkt p;
    Liste.push_back(p);
    

    zunächst eine Instanz auf dem Stack erzeugt wird.



  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    zunächst eine Instanz auf dem Stack erzeugt wird.

    Wenn das dein Problem ist, dann schau dir emplace_back an.



  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    Liste.push_back(punkt());
    Liste[1].setPunkt();
    

    Das ist aber ganz schlechter Code, denn wenn vorher schon mehr Elemente in der Liste wären, dann würdest du mit [1] das falsche Element ändern.
    Wenn schon, dann: List.back().setPunkt();

    Mach dir als Anfänger nicht so Gedanken um (scheinbare) Performance - die Compiler optimieren sowieso in den meisten Fällen solche Aufrufe (z.B. in dem sie nur die CPU-Register benutzen).
    Der Code sollte so geschrieben sein, daß er verständlich ist (auch für andere) und man einfacher diesen auch ändern (erweitern) kann.



  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    Liste.push_back(punkt());
    Liste[1].setPunkt();

    Wenn du direkt nach dem hinzufügen auch noch Dinge ändern willst, mach dir doch gleich einen passenden Konstruktor. Dann sparst du dir den "setPunkt"-Aufruf.



  • Stimmt, "setPunkt" sollte im Konstruktor stehen.



  • Mal nach emplace back und initializer List googeln.



  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    Stimmt, "setPunkt" sollte im Konstruktor stehen.

    In Zukunft Du bitte zeigen vollständige Code. Nicht nur eine Definition einer Klasse. Danke.



  • Für die Vollständigkeit:

    Möglichkeit 1:
    punkt.cpp sieht so aus:

    #include "punkt.h"
    #include <iostream>
    
    punkt::punkt()
    {
        setPunkt();
    }
    
    void punkt::setPunkt()
    {
        std::cout<<"X Koordinate: ";
        std::cin>>this->x;
        std::cout<<"Y Koordinate: ";
        std::cin>>this->y;
    }
    
    void punkt::getPunkt()
    {
        std::cout<<this->x<<" ";
        std::cout<<this->y<<std::endl;
    }
    

    Möglichkeit 2:
    punkt.cpp sieht so aus:

    #include "punkt.h"
    #include <iostream>
    
    punkt::punkt()
    {
        std::cout<<"X Koordinate: ";
        std::cin>>this->x;
        std::cout<<"Y Koordinate: ";
        std::cin>>this->y;
    }
    
    
    void punkt::getPunkt()
    {
        std::cout<<this->x<<" ";
        std::cout<<this->y<<std::endl;
    }
    

    wobei man hier "setPunkt" nicht mehr braucht



  • Ähm. setPunkt sollte nicht einlesen und ausgeben. Ansonsten ist doch die Funktionalität der Punkt-Klasse sehr eingeschränkt. Ich würde mit eher 2 Funktionen setX und setY vorstellen, die jeweils einen Parameter haben und den Wert dann setzen. "Einlesen von cin" ist nicht die Kernkompetenz von Punkt!



  • So ist es natürlich am elegantesten

    void punkt::setx(int x)
    {
        this->mx = x;
    }
    
    void punkt::sety(int y)
    {
        this->my = y;
    }
    


  • So ist es natürlich am elogantesten

    struct punkt
    {
        int x;
        int y;
    };
    


  • @theAnfänger77 sagte in Klasseninstanz über std::vector erzeugen:

    So ist es natürlich am elegantesten

    void punkt::setx(int x)
    {
        this->mx = x;
    }
    
    void punkt::sety(int y)
    {
        this->my = y;
    }
    

    Schon besser. Das "this->" kannst du dir übrigens sparen.
    Zu Übungszwecken könntest du noch Operatoren defininieren, damit man mit den Punkten auch rechnen kann.
    Die Rule-Of-Five wäre hier auch sinnvoll angewendet, denn mit so einer Punkt-Klasse will man üblicherweise alles mögliche machen.

    Eine Funktion zur Berechnung der Distanz zweier Punkte wäre auch noch sinnvoll.



  • @It0101 sagte in Klasseninstanz über std::vector erzeugen:

    Zu Übungszwecken könntest du noch Operatoren defininieren, damit man mit den Punkten auch rechnen kann.

    Ich kann mir gerade keinen sinnvollen Usecase vorstellen, bei dem man 2 Punkte addieren oder multiplizieren können sollte. An was hattest du konkret gedacht? Ich finde, dass auch Übungszwecke zumindest halbwegs sinnvoll sein sollten.

    Die Rule-Of-Five wäre hier auch sinnvoll angewendet, denn mit so einer Punkt-Klasse will man üblicherweise alles mögliche machen.

    Rule of five für Punkte?! Was soll denn deine Punktklasse alles machen? Ist doch eher ein typisches Beispiel für Rule of Zero!

    Eine Funktion zur Berechnung der Distanz zweier Punkte wäre auch noch sinnvoll.

    Aber sicher nicht innerhalb der Punkt-Klasse. Fängt schon damit an, dass man erstmal "Distanz" definieren müsste (welche Metrik?).



  • Was soll die Rule-Of-Five (s.a. The rule of three/five/zero) hier bringen? Weder eigener Destruktor, Kopierkonstruktor oder Zuweisungsoperator sind hier sinnvoll...



  • @Th69
    Es ist eine Übungsaufgabe. Jetzt macht euch mal nicht ins Hemd. Da will man mal jemanden motivieren, Dinge anzuwenden, die er sonst vielleicht nicht anwendet und ihr redet das schlecht. Man man... eure pädagogischen Fähigkeiten sind ungefähr das was man bekommt, wenn man 1 durch unendlich teilt... 😃

    @wob: Punkte addieren macht keinen Sinn? Vector-Rechnung hattest du aber in der Schule oder? 😉



  • @It0101 sagte in Klasseninstanz über std::vector erzeugen:

    @wob: Punkte addieren macht keinen Sinn? Vector-Rechnung hattest du aber in der Schule oder?

    Ja, ich schon. Du auch? Aber hast du da Punkte addiert? Ich nicht. Ich habe dort Vektoren addiert.



  • @It0101: Klar, wir packen jedes Pattern in eine Übungsaufgabe!???


Log in to reply