Fehlender Standardkonstruktor



  • Hallo,

    habe folgendes Problem. Die Programmbibliothek bullet physics hat z.B. für die Klasse btBoxShape keinen Standardkonstruktor.

    Zudem muss (davon gehe ich zumindest aus) ein Objekt dieser Klasse im Speicher erhalten bleiben (sonst kommt eine Fehlermeldung), auch wenn damit ein btRigidBody "konstruiert" wird.

    Momentane Klasse:

    class BoxRigidBody
    {
    public:
    	BoxRigidBody() :
    		shape(btBoxShape(btVector3(5.f, 5.f, 5.f))), // möchte shape nicht im Konstruktor initialisieren
    		rigidBody(btRigidBody(btRigidBody::btRigidBodyConstructionInfo(0, nullptr, nullptr)))
    	{
    		btVector3 inertia;
    		shape.calculateLocalInertia(1, inertia);
    		rigidBody.setMassProps(1, inertia);
    		rigidBody.setCollisionShape(&shape);
    		//rigidBody.setMotionState	
    	}
    	btRigidBody rigidBody;
    private:
    	btBoxShape shape;
    };
    

    Möchte auf newund deleteverzichten und trotzdem ein Objekt dieser Klasse definieren können (z.B. in einer anderen Klasse) ohne es gleich auch initialisieren zu müssen.

    btRigidBody hat zwar auch keinen Standardkonstruktor, es ist aber möglich den Konstruktor mit 0 und nullptrusw. aufzurufen und anschliessend pointer auf die gebrauchten Objekte zu übergeben (siehe Codebeispiel).

    Dann habe ich noch den Eindruck, dass die "Box" oder der cuboid viel zu langsam fällt, verglichen zu einem normalen Gegenstand der auf den Boden fällt, obwohl .setGravity(btVector3(0, -10, 0))eingestellt ist (also etwas mehr als die "Erdanziehung").

    Weiss jemand wie man diese zwei Probleme lösen kann?



  • Du könntest std::optional nutzen. Damit ist es dir möglich, die Erstellung des Objekts zu verzögern, ohne irgendwas auf den Heap packen zu müssen. Ist halt erst ab c++17 verfügbar.



  • @dnkpp Danke für die Antwort 🖖

    Wäre es dann nicht fast einfacher std::unique_ptr zu verwenden?



  • Dann hast du das Ganze aber wieder auf dem Heap. Letztendlich, klar; ist auch eine Lösung.



  • Kenne Heap und Stack nur sehr oberflächlich (manchmal frage ich mich sogar, ob es wirklich einen Unterschied gibt). Bullet Physics leitet einem ja fast durch die fehlenden Standardkonstruktoren zum Heap, zudem werden in Tutorials new und delete gebraucht.

    Wenn es nur möglich sein soll einem Objekt nur einmal Werte zuzuweisen, ist es vermutlich praktisch nur Initialisierung über den Konstruktor zuzulassen. Ich bevorzuge es im Moment aber, die Objekte einfach in der Klasse Scene definieren zu können und in zwei Memberfunktionen verwenden zu können, ohne für die Klasse Scene einen Konstruktor schreiben zu müssen.

    class Scene
    {
    public:
    
        Shader shader;
        
        CuboidShape cuboid;
    
        PlaneRigidBody groundplane;
        BoxRigidBody box;
    
        void Setup();
        void RenderScene();
    };
    


  • @titan99_ sagte in Fehlender Standardkonstruktor (Bullet Physics):

    Kenne Heap und Stack nur sehr oberflächlich (manchmal frage ich mich sogar, ob es wirklich einen Unterschied gibt).

    Also dann solltest du es wenigstens einmal nachlesen, z.B. Stack und Heap.

    Und deine Klasse Scene ist m.E. so auch nicht sinnvoll, wenn du die 4 Member öffentlich machst, denn dadurch hast du doch keine Garantie über den Zustand wenn du in den Methoden darauf zugreifst...



  • @th69 Habe kurz versucht eine Variable im Stack zu deleten; bei delete kommt eine Laufzeit-Fehlermeldung.

    int main()
    {
        int stackvariable = 37;
        int* stackpointer = &stackvariable;
        std::cout << *stackpointer << '\n';
    	
        //delete stackpointer;
    
        //std::cout << stackvariable << '\n';
        //std::cout << *stackpointer << '\n';
    
    	system("pause");
    }
    

    @th69 sagte in Fehlender Standardkonstruktor (Bullet Physics):

    Und deine Klasse Scene ist m.E. so auch nicht sinnvoll, wenn du die 4 Member öffentlich machst, denn dadurch hast du doch keine Garantie über den Zustand wenn du in den Methoden darauf zugreifst...

    Die Klasse Scene ist auch sehr provisorisch, sie könnten auch private sein.



  • @titan99_ sagte in Fehlender Standardkonstruktor (Bullet Physics):

    @th69 Habe kurz versucht eine Variable im Stack zu deleten; bei delete kommt eine Laufzeit-Fehlermeldung.

    An delete darf man nur Pointer verfüttern, die von new kommen. An delete[] nur die von new T[].



  • Du kannst den Speicher mit sowas wie "uint8_t box[sizeof(BoxRigidBody)];" anlegen und spaeter mit einem in-placement new initialisieren "new (box)BoxRigidBody(...)". In dem Fall darfst du natuerlich wieder nicht delete aufrufen, aber den Destruktor solltest du schon irgendwann ausfuehren. Wenn du danach googlen willst, sind deine keywords "Fast PImpl". Du solltest natuerlich nicht alles von Hand machen, sondern einen fertigen Wrapper nutzen, z.B.
    https://www.gamedev.net/articles/programming/general-and-gameplay-programming/static-zero-overhead-probably-pimpl-in-c-r4338/