Objekte abgeleiteter Klassen in einem Vector



  • Hallo :-),
    ich habe 3 Klassen: Pt, Sgt und Rct.
    Sgt ist von Pt abgeleitet.
    Rct ist von Sgt abgeleitet.

    Es gibt für alle drei Klassen unterschiedliche Print-Funktionen.
    In der Header-Datei jeder Klasse ist außerdem der operator<< überschrieben, der die Print(ostream& s)-Funktion aufruft.

    Wenn ich jetzt Objekte aller drei Klassen erzeuge und sie über einen Zeiger ausgebe, klappt alles und die Print-Funktion der richtigen Klasse wird verwendet.

    Packe ich diese Zeiger der Objekte jetzt in einen vector<Pt*> klappt das ganze nicht mehr 😕 - hier wird jetzt immer die Print-Funktion von der Basis-Klasse Pt aufgerufen.

    Hier der Code:
    main:

    #include "Rct.h"
    #include <iostream>
    #include <stdlib.h>
    #include <vector>
    using namespace std;
    
    int main() {
    	Pt* a = new Pt();
    	Pt* b = new Pt(1,2);
    	Pt* c = new Pt(7,8);
    	Sgt* ab = new Sgt(*a,*b);
    	Sgt* bc = new Sgt(*b,*c);
    	Rct* r1 = new Rct(*b,*c);
    	cout << *a << "\n" << *ab << "\n" << *bc << "\n" << *r1;		// here the correct print()-function is called.
    
    	vector<Pt*> objects;
    	objects.push_back(a);	// adding objects
    	objects.push_back(ab);
    	objects.push_back(r1);
    
    	cout << "\nIterator-Test: \n";
        for(std::vector<Pt*>::const_iterator i = objects.begin(); i != objects.end(); ++i)
          cout << **i << endl;	// here it's not the correct function anymore.
        	//*i->Print();
    
    	return 0;
    }
    

    Pt.h:

    #include <iostream>
    
    #ifndef PT_H_
    #define PT_H_
    
    using namespace std;
    
    class Pt {
    public:
    	double x, y;
    	Pt();
    	Pt(double X, double Y);
    	virtual ~Pt();
    
    	virtual void Print(ostream& s) const; //{ s << "Pt(" << x << "," << y << ")"; }
    };
    
    inline ostream& operator<<(ostream& s, Pt pt) { // Insert into a stream
    	pt.Print(s);
    	return s;
    }
    
    #endif /* PT_H_ */
    

    Pt.cpp:

    #include "Pt.h"
    
    Pt::Pt() : x(0), y(0) {}
    Pt::Pt(double X, double Y) : x(X), y(Y) {}
    
    Pt::~Pt() {}
    
    void Pt::Print(ostream& s) const
    	{s << "Pt(" << x << "," << y << ")"; }
    

    Sgt.h:

    #include <iostream>
    #include "Pt.h"
    
    #ifndef SGT_H_
    #define SGT_H_
    
    class Sgt : public Pt {
    public:
    	Pt p2;
    	Sgt();
    	Sgt(Pt P1, Pt P2);
    	virtual ~Sgt();
    	void Print(ostream& s) const;
    };
    
    inline ostream& operator<<(ostream& s, Sgt sgt) { // Insert dans un flux
    	sgt.Print(s);
    	return s;
    }
    
    #endif /* SGT_H_ */
    

    Sgt.cpp:

    #include "Sgt.h"
    
    Sgt::Sgt() : p2(Pt(0,0)) {}
    Sgt::Sgt(Pt P1, Pt P2) : Pt(P1), p2(P2) {}
    
    Sgt::~Sgt() {}
    void Sgt::Print(ostream& s) const {
    		s << "Sgt( "<<Pt(x,y) << ", " << p2 << " )";
    }
    

    Rct.h:

    #include "Sgt.h"
    #ifndef RCT_H_
    #define RCT_H_
    
    class Rct : public Sgt {
    public:
    	Rct();
    	Rct(Pt p1, Pt p2);
    	virtual ~Rct();
    
    	void Print(ostream& s) const;
    };
    inline ostream& operator<<(ostream& s, Rct rct) { // Insert dans un flux
    	rct.Print(s);
    	return s;
    }
    
    #endif /* RCT_H_ */
    

    Rct.cpp:

    #include "Rct.h"
    
    Rct::Rct() {}
    Rct::Rct(Pt p1, Pt p2) : Sgt(p1, p2) {}
    
    void Rct::Print(ostream& s) const {
    		s << "Rct( "<<Pt(x,y) << ", " << p2 << " )";
    }
    
    Rct::~Rct() {}
    

    Vielen Dank schonmal im Voraus 😉



  • ...



  • lukas.braband schrieb:

    inline ostream& operator<<(ostream& s, Rct rct) { // Insert dans un flux
    	rct.Print(s);
    	return s;
    }
    

    Tss...die Franzosen... 😉
    Nimm eine Referenz oder einen Zeiger auf Pt , damit der Compiler die richtige Print() Funktion aufruft. Zeiger sind allerdings unüblich.

    Dein Beispiel revisited:

    #include <iostream>
    #include <vector>
    #include <memory>
    
    struct Pt{
      Pt(int x=0, int y=0) : x(x), y(y) {}
      virtual void print(std::ostream& out) const {
        out << "Pt(" << x << "," << y << ")";
      }
      virtual ~Pt() {}
    private:
      int x,y;
    };
    
    std::ostream& operator<<(std::ostream& out, const Pt& pt) {
      pt.print(out);
      return out;
    }
    
    struct Sgt : Pt{
      Sgt(){}
      Sgt(const Pt& p1, const Pt& p2) : Pt(p1), p2(p2) {}
      void print(std::ostream& out) const {
        out << "Sgt(" << static_cast<Pt>(*this) << "," << p2 << ")";
      }  
    private:
      Pt p2;
    };
    
    struct Rct : Sgt{
      Rct() {}
      Rct(const Pt& p1, const Pt& p2) : Sgt(p1, p2) {}
      void print(std::ostream& out) const {
        out << "Rct(" << static_cast<Sgt>(*this) << ")";
      }
    };
    
    int main(){
      std::vector<std::unique_ptr<Pt>> soldiers;
      soldiers.emplace_back(new Pt());
      soldiers.emplace_back(new Pt(1,2));
      soldiers.emplace_back(new Pt(7,8));
      soldiers.emplace_back(new Sgt(*soldiers[0], *soldiers[1]));
      soldiers.emplace_back(new Sgt(*soldiers[1], *soldiers[2]));
      soldiers.emplace_back(new Rct(*soldiers[1], *soldiers[2]));
    
      for(const auto& it : soldiers)
        std::cout << *it << '\n';
    }
    

    Bonne chance!



  • Furble Wurble schrieb:

    Tss...die Franzosen... 😉

    uups, da hab ich doch tatsächlich noch einen Franz-Kommentar vergessen^^.
    Haha, ja, mache gerade 2 Auslands-Semester in Südfrankreich :). War immerhin positiv überrascht, dass alle Variablennamen englisch sind - gut wenn, die das aussprechen kann man sich schon wieder streiten, ob das englisch sein soll haha^^, aber gut, das ist ne andere Sache^^.

    Also gut - lange Rede, kurzer Sinn.
    Vielen Dank für eure schnelle Hilfe 😉 👍 !
    Das Grobe habe ich soweit erstmal verstanden.
    Ich verstehe allerdings noch nicht so ganz, wozu die static-casts in den Print-Funktionen jetzt gut sein sollen 😕 ?

    @ Swordfish:
    Das ein Rct ein Sgt und ein Sgt ein Pt sein soll, hat sich mein Prof hier ausgedacht 🙄 - ich hab mich auch gewundert :-/.

    Achso ja:
    tausendmal :p :p 😃



  • ...


Anmelden zum Antworten