Vererbung?



  • Hallo,

    ich hänge schon wieder an diesem Thema und ich kapiere es einfach nicht. Das scheint eine unüberwindbare Verständnisgrenze für mich zu sein. Tut also einfach so, als wäre ich als Kind vom Wickeltisch gefallen, gutmütig wie Ihr seit, versucht Ihr es trotzdem.

    Als Grundlage möchte ich Kapitel 9 aus dem Buch "C++ eine Einführung" nehmen. Bei dem Beispielcode habe ich nur die Bezeichnungen geändert, damit er lesbarer ist.

    struct Point
    {
      int x;
      int y;
    };
    
    class GraphObject
    {
    public:
    
        GraphObject( Point p = {} ) : point( p ) {}
    
        void draw() const
        {
            std::cout << "\nGraphObject draw at ( "
                      << point.x << ", " << point.y << " )\n";
        }
    
        Point refPoint() const
        {
            return point;
        }
    
    private:
    
        Point point;
    };
    
    class Rect : public GraphObject
    {
    public:
    
        Rect( Point p, int w, int h ) : GraphObject( p ), r_width( w ), r_height( h ) {}
    
        int width() const
        {
            return r_width;
        }
    	
        int height() const
        {
            return r_height;
        }
    
        void draw() const
        {
            std::cout << "\nRect " << r_height << " x "
                      << r_width << " draw at ( "
                      << refPoint().x << ", "
                      << refPoint().y << " )\n";
        }
    
    private:
    
        int r_width;
        int r_height;
    };
    
    int main()
    {
    
      Point p { 50, 50 };
      std::cout << "Point ( " << p.x << ", " << p.y << " )\n";
    
      GraphObject g( p );
      g.draw();
    
      Rect r( p, 40, 20 );
      r.draw();
    }
    

    Hier werden die Koordinaten für Point händisch eingegeben. Jetzt möchte ich statt Point eine eigene struct nehmen in der Form

    struct Object
    {
        std::size_t vc;
        std::vector<int> x;
        std::vector<int> y;
        std::vector<int> z;
    
        std::size_t edges;
        std::vector<std::size_t> a;
        std::vector<std::size_t> b;
    };
    

    Die dortigen Werte möchte ich nicht händisch eingeben, sondern von einer anderen struct übernehmen.

    struct Line
    {
        std::size_t vc = 2;
        std::vector<int> x_vec                 = {  -1,  1 };
        std::vector<int> y_vec                 = {   0,  0 };
        std::vector<int> z_vec                 = {   0,  0 };
    
        std::size_t edges = 1;
        std::vector<std::size_t> a_vec         = {  0 };
        std::vector<std::size_t> b_vec         = {  1 };
    };
    

    Aber ich habe nicht den blassesten Schimmer wie ich das bewerkstelligen soll.



  • Ich habe nicht den blassesten Schimmer, was eigentlich das Problem ist. Was hat das mit Vererbung zu tun?



  • Die gezeigten Klassen hast du aus dem Buch übernommen? Eine Basisklasse für einen Punkt? Ohne virtual?



  • Wofür brauchst Du 2 Structs Line und Object die (bis auf die Membernamen und Initialisierer) exakt gleich aussehen?



  • @manni66 sagte in Vererbung?:

    Die gezeigten Klassen hast du aus dem Buch übernommen? Eine Basisklasse für einen Punkt? Ohne virtual?

    virtual kommt zwar im selben Kapitel, aber erst unter Polymorphismus.



  • @manni66 sagte in Vererbung?:

    Ich habe nicht den blassesten Schimmer, was eigentlich das Problem ist. Was hat das mit Vererbung zu tun?

    Erbt Rect nicht von GraphObject?

    Eigentlich verstehe ich selbst nicht, warum das so machen sollte. Ich selbst würde das viel simpler machen, ohne irgendeine Vererbung. Aber es wird wohl darum gehen, Beispiele zu bringen.

    Aber ich verstehe davon so wenig, das ich nichtmal ein eigenes Beispiel zeigen kann.



  • Meine erste Entwicklung sah so aus:

    class G3DObject
    {
    public:
    
        template<typename Object>
        G3DObject( const Object& obj, double length = 1.0 ) : side_length( length )
        {
            createObject( obj );
        }
    
    
        void printObject() const;
    
    
    
    private:
    
        double side_length = 0;
    
        struct Point
        {
            int x = 0;
            int y = 0;
            int z = 0;
        } point;
        std::vector<Point> points;
    
        struct FloatPoint
        {
            double x = 0;
            double y = 0;
            double z = 0;
        } fpoint;
        std::vector<FloatPoint> fpoints;
    
        struct Edge
        {
            std::size_t a = 0;
            std::size_t b = 0;
        } edge;
        std::vector<Edge> edges;
    
        template<typename Object>
        void createObject( const Object& obj );
    };
    
    template<typename Object>
    inline void G3DObject::createObject( const Object& obj )
    {
        for ( std::size_t i = 0; i < obj.vc; ++i )
        {
            point.x = obj.x[ i ];
            point.y = obj.y[ i ];
            point.z = obj.z[ i ];
            points.push_back( point );
            fpoint.x = point.x * side_length;
            fpoint.y = point.y * side_length;
            fpoint.z = point.z * side_length;
            fpoints.push_back( fpoint );
        }
        for ( std::size_t i = 0; i < obj.edges; ++i )
        {
            edge.a = obj.a[ i ];
            edge.b = obj.b[ i ];
            edges.push_back( edge );
        }
    }
    
    inline void G3DObject::printObject() const
    {
        for ( const auto& fpoint : fpoints )
        {
            std::cout << "x: " << fpoint.x << "  y: " << fpoint.y << " z: " << fpoint.z << '\n';
        }
    }
    
    

    Dies wurde aber wegen einigen Stellen bemängelt, vor allem die umständliche Erzeugung eines Objekt.
    Für mich kam das immer so vor, als wäre Vererbung der Schlüssel für all meine Probleme. In diesem Fall sollte dann statt wie ich es geschrieben habe, Object von G3DObject erben. template würde nicht mehr verwendet werden.



  • @lemon03 sagte in Vererbung?:

    @manni66 sagte in Vererbung?:

    Ich habe nicht den blassesten Schimmer, was eigentlich das Problem ist. Was hat das mit Vererbung zu tun?

    Erbt Rect nicht von GraphObject?

    Ja, aber was hat das mit Object/Line bzw. mit deinem Problem zu tun?



  • @lemon03 sagte in Vererbung?:

    @manni66 sagte in Vererbung?:

    Die gezeigten Klassen hast du aus dem Buch übernommen? Eine Basisklasse für einen Punkt? Ohne virtual?

    virtual kommt zwar im selben Kapitel, aber erst unter Polymorphismus.

    Ich kenne das Buch nicht, aber das hier macht jetzt keinen guten Eindruck.



  • Es ist von Ulrich Breymann und ich denke, es soll sich eher an die jüngere Gemeinde richten 😉 Es hat auch nur Taschenbuchformat und nur ca 400 Seiten. Es wird versucht, anhand eines Spiel die Grundlagen beizubringen. Im obigen Beispiel gibt es zwar nur eine Konsole-Ausgabe, aber grundsätzlich geschieht dies über die SFML.

    Deswegen habe ich es mir aber nicht geholt, sondern eher als Test, ob ich die ersten Kapitel auf Anhieb verstehen kann.

    Und ich hänge wieder und immer wieder bei der Vererbung fest. Es ist fast ein wenig hoffnungslos. Wie in der Schule bei Mathe. Ging alles ganz flott, aber im Leistungskurs dann musste ich aussteigen. Da war dann der Wickeltisch.



  • @lemon03 sagte in Vererbung?:

    Und ich hänge wieder und immer wieder bei der Vererbung fest.

    Aha. Aus dem ganzen Thread wird aber leider nicht klar, wo Deine Probleme damit liegen.



  • Ich glaube, wenn ich wenigstens meine Schwächen darin darlegen könnte, wirklich beschreiben könnte, was ich nicht verstehe, wär ich schon ein gutes Stück weiter.

    Ich versteh das ganze Konzept von Vererbung nicht. Warum man das macht, wie man das macht. Ich kann ja nicht mal ein Beispiel schreiben, wo ich darlegen kann, was ich nicht verstehe.



  • Naja, worauf das hinausläuft, dürfte klar sein. Irgendwann wirst du eine Liste von GraphObjects haben. Damit kannst du unterschiedliche Implementierungen oder Varianten (Rect, Line) zusammen verwalten. Brauchst aber noch Polymorphie, damit sie was sinnvolles tun.



  • Ist vielleicht ein wenig unglücklich, das ich mit den obigen Beispielen angefangen habe.

    Mir würde es schon reichen zu verstehen, wie eine Klasse A von Klasse B erbt. Klasse A soll aber Parameter haben, die in Klasse B verarbeitet werden.



  • Was heißt "verarbeitet"? Du musst dich schon präziser ausdrücken.
    Wie du erbst, hast du in deinen Beispielen ja schon gesehen. Rect erbt von GraphObject.
    Das kann auf die Member von GraphObject nicht zugreifen, weil sie private sind. Das könnte auf public oder protected Member zugreifen.



  • @mechanics sagte in Vererbung?:

    Was heißt "verarbeitet"? Du musst dich schon präziser ausdrücken.

    Wenn ich das nur könnte. Dann würden wir hier wahrscheinlich gar nicht schreiben müssen.



  • Schau dir vielleicht mal die Wikipedia Artikel zu dem Thema an. Ich hab keine Ahnung, wie gut die sind, aber ich denke, du solltest da erstmal etwas weg von der C++ Umsetzung, und einfach nur das Konzept verstehen. Wenn du weißt, was du damit machen kannst, ist das wie dann nicht mehr wirklich schwierig.



  • Solange Wurst und Wurstbrot nicht von Supermarkt erben ist alles OK 😉



  • @lemon03 sagte in Vererbung?:

    Mir würde es schon reichen zu verstehen, wie eine Klasse A von Klasse B erbt. Klasse A soll aber Parameter haben, die in Klasse B verarbeitet werden.

    class Rect : public GraphObject Also an dieser Stelle erbt Klasse A (Rect) von Klasse B (GraphObject). public kann lässt sich als wie es erbt vorstellen. public AFAIK ändert aber nicht public, protected oder private in der Basisklasse (die Klasse von der geerbt wird).

    Falls das wie das Problem sein sollte, könnte es hilfreich sein, zu verstehen versuchen, was diese an der erwähnten Stelle zu suchen haben. (stellen, stehen, suchen, wähnen) :smiling_face_with_open_mouth_closed_eyes:🤧



  • Jepp, danke. Freundlich von Euch 🙂

    Irgendwann werde ich das knacken. Aber bis dahin mach ich erstmal ein wenig Kleinkram weiter.