template in Klassen



  • @lemon03 sagte in template in Klassen:

    als ob Du nicht sicher bist, das dieser Vorschlag ist, was ich mir vorstelle. Das kann ich im Moment nicht sagen, weil ich ihn erst umsetzen müsste

    Wenn du das kurze & einfache Stückchen Code nicht lesen und verstehen kannst, dann ist Üben angesagt.



  • Das verstehe ich. Zum Glück drehe ich keine Däumchen, sondern übe eben.

    Allerdings kann ich nicht nur den Code auf Anhieb verstehen, ich weiß auch nicht, wie ich beliebige_struct deuten soll? Klar, ist meine zitierte Bezeichnung, aber wenn es nun eine weitere struct namens noch_eine_beliebige_struct gibt, bin ich doch kein Stück weiter gekommen?

    Aber selbst wenn, kompilieren tuts eh nicht. Hat die obige Vorgehensweise einen bestimmten Namen, damit ich mich da besser informieren kann?



  • Oder halt stop!

    Bin ja schon weiter. Etwas weiter oben hat ja funktioniert. Der Rest ist nur Sahne, um eine händische Erzeugung der Objecte vor der Übergabe zu übergehen.

    Das kapiere ich vielleicht auch irgendwann mal, also belassen wir es dabei. Also ich werde es jedenfalls. Danke.



  • @lemon03 sagte in template in Klassen:

    Aber selbst wenn, kompilieren tuts eh nicht.

    wtf?? tut es wohl!?

    @lemon03 sagte in template in Klassen:

    Klar, ist meine zitierte Bezeichnung, aber wenn es nun eine weitere struct namens noch_eine_beliebige_struct gibt, bin ich doch kein Stück weiter gekommen?

    struct beliebige_struct { int foo; };
    struct noch_eine_beliebige_struct{ int baz; };
    
    template<typename T>
    class G3DObject
    {
        T instanz;
        // ...
    };
    
    // ...
    
    G3DObject<beliebige_struct> bar;
    G3DObject<noch_eine_beliebige_struct> qax;
    // ...
    

    oder, je nach dem

    struct beliebige_struct { int foo; };
    struct noch_eine_beliebige_struct{ int baz; };
    
    template<typename T, typename U>
    class G3DObject
    {
        T instanz_1;
        U instanz_2;
        // ...
    };
    
    // ...
    
    G3DObject<beliebige_struct, noch_eine_beliebige_struct> bar;
    

    aus deinen Beiträgen wird nicht wirklich klar, was es werden soll, wenns fertig ist. Oder, was Du mit solchen schwammigen Aussagen meinst:

    @lemon03 sagte in template in Klassen:

    Der Rest ist nur Sahne, um eine händische Erzeugung der Objecte vor der Übergabe zu übergehen.

    @lemon03 sagte in template in Klassen:

    Hat die obige Vorgehensweise einen bestimmten Namen, damit ich mich da besser informieren kann?

    Template Classes.



  • Danke, aber genau diese Aufzählung aller vorhandener structs wollte ich doch vermeiden. Ich kann doch nicht jedesmal, wenn eine neue struct dazu kommt, die Klasse umschreiben. Zwar hält sich die tatsächliche Anzahl der structs in Grenzen, aber ich wollte das möglichst flexibel.

    Es gibt diese Klasse G3DObject und vollkommen unabhängig davon einen header voll structs. Es kann eine sein oder hunderte, die Klasse selbst soll nicht mehr angefasst werden.

    Aber wie geschrieben, diese Sache ist schon gelöst. Zwar mit den Schönheitsflecken

    Rect_( rectObj ); //hier
    Triangle_( trObj ); //und hier
    G3DObject rect{ rectObj };
    G3DObject triangle{ trObj };
    rect.printObject();
    std::cout << '\n';
    triangle.printObject();
    ready();
    

    aber ansonsten wie gewünscht.

    PS: die schwammige Ausdrucksweise kommt wahrscheinlich daher, das ich keine Ahnung habe, wie solche Techniken bezeichnet werden und ich sie deshalb in Prosa umschreiben muss. Falls ich irgendwann ein ähnliches Problem haben sollte, habe ich dann immerhin schon das Stichwort 'Template Classes'. Davor hatte ich gar nichts.



  • Brauchst du denn die Objekte rectObj und trObj überhaupt außerhalb deiner Klasse?

    Außerdem finde ich die Klammern in beiden mit "hier" markierten Zeilen störend/verwirrend.



  • Jupp, sehe ich auch so. Fangen wir wieder von vorne an. Ich habe eine Klasse und einen header voller structs, die übergeben werden wollen.

    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';
        }
    }
    

    Wie mache ich das besser? Bitte mit einem minimal-kompilierbaren Beispiel.

    EDIT: Sorry, ich werde für einige Stunden abwesend sein. Bitte nicht wundern.



  • Wenn du nicht ständig neue structs für neue Formen machen willst, dann musst du eine struct machen, die eine Form beschreibt:

    • Ist die Form rund oder hat sie Ecken?
    • Wie viele Ecken hat die Form?
    • Zwischen welchen Ecken besteht eine Verbindung?
    • Wie ist die Verbindung zwischen den Ecken? Gerade Linie? Kurve?
      Die Daten kannst du dann dem Konstruktor übergeben und eine gewünschte Form erzeugen.

    Andere Möglichkeiten sehe ich nicht. Entweder du machst für unterschiedliche Formen mehrere structs, oder du machst eine struct und beschreibst eine Form.



  • Hallo, sorry, hat etwas länger gedauert, ist aber zum Glück nicht viel aufgelaufen. Will versuchen, die Fragen ebenso strukturiert zu beantworten.

    Ich will nicht ständig neue structs für neue Formen machen, sie existieren schon. Allerdings soll die Anzahl und auch die Bezeichnungen für die Klasse unbekannt sein. Erst bei der Übergabe ist klar, um welche struct, um welche Form es sich handelt. Und ich möchte, selbst wenn nur theoretisch, neue Formen hinzufügen können, ohne etwas an der Klasse zu ändern.

    • Die Formen bestehen aus Eckpunkten und Kanten.
    • Die maximale Anzahl der Ecken einer Form sind 360. Damit wird angenähert ein Kreis gebildet.
    • Alle zwei Ecken sind mit einer Kante verbunden. Es sind immer geschlossene Formen. Die Anzahl der Kanten sind Ecken -1.
    • Die Kanten sind gerade Linien zwischen zwei Punkten.

    Durch Deine abschließende Schlussfolgerung werde ich bestätigt, alles so sein zu lassen wie geplant.

    Alle bisher erstellten Formen können auch durch eine einzige Form, nämlich durch ein regelmäßiges Polygon erstellt werden, das durch die Anzahl der Eckpunkte bestimmt wird. Dies wurde schon implementiert.

    Daneben gibt es noch den Würfel und die Pyramide. Schön wäre es, auch diese Formen durch ein regelmäßiges Polyeder erstellen zu können. Habe aber noch keine Berechnungsgrundlage dafür. Habe auch noch nicht wirklich nachgeforscht. Danke.



  • Ich frage mich gerade mehrere Dinge:

    1. Sind Templates überhaupt das richtige Mittel der Wahl hier? Die Klassen, die du übergeben kannst, müssen ja mindestens mal die Member vc, x,y,z, edges,a und b haben. Man könnte auch über Polymorphie nachdenken und dieses in einer Shape-Klasse einbauen.
    2. Deine Methode createObject scheint mir eher sowas wie eine Kopie zu erzeugen? Ich bin mit dem Namen nicht einverstanden. Wäre sowas wie "initializeFromObject" oder "initializeFromShape" nicht besser? Bei "create" stelle ich mit immer vor, dass darin irgendwas erzeugt wird (und auch zurückgegeben wird), also à la auto obj = createObject();.
    3. Deine structs Point und FloatPoint sind dagegen ja mal klare Template-Kandidaten! Ich würde sie außerhalb von G3DObject deklarieren. Ich würde das dann Point3d<int> und Point3d<double> nennen. Zumal man bei deinem FloatPoint sich auch wundert, dass da keine floats, sondern doubles verwendet werden. Gut, double ist auch Fließkomma, aber wozu hier die Ambiguität einbauen? (abgesehen davon, dass es Point3d-Klassen bestimmt wie Sand am Meer gibt)


  • Ich möchte mich gerne erst mal auf Punkt1 konzentrieren, ob template hier die richtige Wahl ist.

    Nun, ich kenne nichts anderes. Das ist der einzige Grund. So wie die Klasse dort steht, zeige ich sie zum ersten Mal. Was ich vorher hatte, war höflich gesagt eine Katastrophe.

    Ist ja nicht so, das ich nicht schon über andere Techniken nach gedacht habe, aber welche? Du hast das Stichwort Polymorphie gebracht. Gut, was ist das? Irgendwas mit Vererbung. Schaue ich nach, bringe ein Beispiel, dann ist das schlimmstenfalls ein Aprilscherz, bestenfalls verwechsele ich Begriffe.

    Ich möchte gerne sehen, was im konkreten Fall damit gemeint ist.


Anmelden zum Antworten