Klasse und Objekt in anderer Klasse erstellen



  • Hallo, meine Titel heißen immer irgendwie ähnlich. Diesmal geht es um folgendes. Ich habe einen header mit structs, die einfach aufgerufen werden.

    struct A
    {
        int x = 1;
    };
    
    struct B
    {
        int x = 2;
    };
    
    struct C
    {
        int x = 3;
    };
    
    #include "structs.h"
    #include <iostream>
    
    int main()
    {
        A a;
        B b;
        C c;
    
        std::cout << a.x << b.x << c.x;
    }
    

    Jetzt möchte ich diese structs in einer Klasse verwalten können, weiß aber nicht recht wie. Nur mal am struct A als Beispiel. Ziel ist jede beliebige struct, die im header stehen kann aufrufen zu können.

    #include "structs.h"
    #include <iostream>
    
    class Cl
    {
    public:
        Cl( const A& obj ) : a ( obj ){}
    private:
        A a;
    };
    
    int main()
    {
    
        //Cl A( a ); //???
    }
    


  • Also wenn es mit jedem Typen funktionieren soll, musst du wohl ein Template nutzen. Aber wo liegt das genaue Problem?



  • Ich weiß nicht, wie ich in der main ein Objekt von zB A innerhalb Cl erstelle. Oder vielleicht habe ich ein XY-Problem.

    Es gibt diesen header mit einen Haufen structs. Dazu gibt es Funktionstemplates um diese structs zu verarbeiten. Diese Funktionen sollen jetzt Memberfunktionen der gemeinten Klasse werden, dazu muss ich aber doch erst in der Klasse ein Objekt von solch einem struct erstellen?



  • Kannst du ein komplettes Beispiel zeigen?



  • Wie wärs mit Cl x(A());



  • Aha. Hat das x ne bestimmte Bedeutung oder ist das ein Objekt von Cl?

    Habe Schwierigkeiten nun auf x eines erstellten Objekt von A in Cl zuzugreifen.

    Falls mehr Code wirklich helfen sollte. Zwei structs:

    struct Triangle
    {
        std::size_t vc = 3;
        std::vector<int> _x                 = {  0,  1, -1 };
        std::vector<int> _y                 = {  1, -1, -1 };
        std::vector<int> _z                 = {  0,  0,  0 };
    
        std::size_t edges = 3;
        std::vector<std::size_t> edge_begin = {  0,  1,  2 };
        std::vector<std::size_t> edge_end   = {  1,  2,  0 };
    
        ///////////////////////////////////////////////////////
    
        Values v;
        std::vector<double> x, y, z, xn, yn, zn;
        std::vector<int> cx, cy;
        int side_length = 0;
        bool is_create = false;
    };
    
    struct Rect
    {
        std::size_t vc = 4;
        std::vector<int> _x                 = { -1,  1,  1, -1 };
        std::vector<int> _y                 = {  1,  1, -1, -1 };
        std::vector<int> _z                 = {  0,  0,  0,  0 };
    
        std::size_t edges = 4;
        std::vector<std::size_t> edge_begin = {  0,  1,  2,  3 };
        std::vector<std::size_t> edge_end   = {  1,  2,  3,  0 };
    
        ///////////////////////////////////////////////////////
    
        Values v;
        std::vector<double> x, y, z, xn, yn, zn;
        std::vector<int> cx, cy;
        int side_length = 0;
        bool is_create = false;
    
    };
    

    Eine Funktion:

    template<typename T>
    void scaleFigure( T&,
                      double, double, double );
    template<typename T>
    void scaleFigure( T& fig,
                      double sx, double sy, double sz )
    {
        if ( !fig.is_create )
        {
            std::cerr << "scaleFigure(): object error\n";
            std::cerr << "no figure created\n";
            pressKey();
            return;
        }
        fig.v.scale_x = sx;
        fig.v.scale_y = sy;
        fig.v.scale_z = sz;
    }
    

    Jetzt möchte ich eine neue Klasse Object oder so, die dann wie folgt funktionieren soll:

    int main()
    {
        Object Rect r; //Aufruf von Rect in Object irgendwie
        r.scale( 1.5, 1.5, 1.5 ); //statt dem Funktionstemplate
    }
    


  • So ein Ramsch Junge.

    Aha. Hat das x ne bestimmte Bedeutung oder ist das ein Objekt von Cl?

    Na hilf dir doch selbst! 💡



  • template<typename T>
    void scaleFigure( T& fig, double sx )
    {
    	fig.x = sx;
    }
    
    struct Triangle
    {
    	double x;
    };
    
    struct Rect
    {
    	double x;
    };
    
    struct Object
    {
    	Triangle t;
    	Rect r;
    };
    
    int main()
    {
    	Object o;
    	scaleFigure( o.t, 123 );
    	scaleFigure( o.r, 321 );
    }
    

    Das Design finde ich ingesamt komisch. Wenn ichs jetzt richtig sehe, haben Triangle und Rect exakt dieselben Member. Dann sollte das eigentlich eine struct namens "Form" sein, die abhängig von der Initialisierung ein Triangle oder Rect erstellen kann.



  • out schrieb:

    Das Design finde ich ingesamt komisch.

    Ich weiß. Deshalb will ichs ja ändern.



  • Gibt es eine Möglichkeit, die structs eben nicht in der Klasse zu erklären? Es soll vorher gar nicht klar sein, wieviele structs es gibt. Erst bei der Initialisierung kennt die Klasse dieses struct und kann ein Objekt davon erstellen.

    edit: Bzw, kann ich obige [c]Triangle[/c], [c]Rect[/c] durch ein template ersetzen? Doofe Frage, ich probiere es mal. Wahrscheinlich wieder zu früh gefragt.



  • Vielleicht erklärst du erstmal den Hintergrund deines Programms. Du hast eine Idee X und das Programmziel ist am Ende Y...



  • Deine Denke/Design ist ziemlich krumm.

    1. Willst du nicht lieber erben und dann Polymorphie nutzen?

    Rect : public Shape
    Traingle : public Shape



  • Die structs sollen nur die vertices und die edges beinhalten.

    In der Klasse soll am liebsten im Konstruktor ein Objekt des struct erstellt werden, aber so wie vorher Rect r; in der main, nur eben im Konstruktor. Wobei ich absolut keine Ahnung habe, ob das geht. Ich kenne keine Schreibweise für solches.

    Die Methoden in der Klasse beziehen sich dann auf dieses Objekt.

    @Script
    Kann sein, müsste ich mir mal anschauen.



  • lemon03 schrieb:

    Die structs sollen nur die vertices und die edges beinhalten.

    Die Methoden in der Klasse beziehen sich dann auf dieses Objekt.

    Klingt als würdest du 1A Polymorphie beschreiben, aber nicht kennen.

    class Shape {
        virtual void draw(Surface* surface) = 0;
    };
    class Rect : public Shape {
        void draw(Surface* surface) override 
        {
            // draw this rectangle onto the surface.
        }
    };
    class Triangle : public Shape {
        void draw(Surface* surface) override
        {
            // draw this triangle onto the surface.
        }
    };
    
    int main()
    {
        Surface someSurface;
        std::unique_ptr <Shape> someShape {new Rect};
        someShape->draw(&someSurface);
        someShape.reset(new Triangle);
    
        // Die Code-Zeile zum Zeichnen bleibt gleich, aber es passiert etwas ganz anderes in Abhängigkeit davon was "Shape" denn nun ist.
        someShape->draw(&someSurface);
    }
    

    Das ist sogar ein klassisches Beispiel für die Anwendung von Vererbung.
    Alternative auch umsetzbar mit statischer Polymorphie mit Templates, aber ich behaupte mal, dass du hiermit besser bedient bist.
    Du kannst darin sogar deine Ursprüngliche "Denke" einbaun:

    class ShapePainer
    {
        void paint(Shape const& shape)
        {
            shape.draw(&mySurface); // zeichnet je nachdem was Shape wirklich ist.
        }
    
    private:
        Surface mySurface;
    };
    

    Wenn du Fragen zum Code hast, oder du das doch kennst aber nicht meinst, bitte antworten und fragen.



  • Vielen Dank vorerst 🙂

    Ich kenne es noch nicht, da Du aber einen Sinn in meinen Wünschen gefunden hast, wird das wohl hinkommen. Über einige Schlüsselwörter muss ich noch nachlesen und pointer habe ich auch noch nie benutzt.

    Aber ich versuche es mal umzusetzen, wie weit ich komme.



  • Ich glaube, ich bin für solche höheren Techniken zu blöd. Eigentlich wusste ich gar nicht, wo ich trotz der Beispiel anfangen soll. Also wollte ich mich erst mal über Vererbung informieren. Habe sogar ins Buch geschaut. Hilft aber nicht viel, wie man sehen wird.

    Ist aber besser, ich starte deswegen einen neuen Thread.


Log in to reply