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
new
unddelete
verzichten 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
undnullptr
usw. 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 vonnew
kommen. Andelete[]
nur die vonnew 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/