C++ Void Zeiger | Auf Funktionen zugreifen?

2 Antworten

Void Pointer sind bäääh, meistens jedenfalls.

Pointer in C++ sind solange 'pfui' solange Du die einzelnen Objektinstanzen nicht dynamisch auf dem Heap erzeugen mußt oder willst.

Was Du eigentlich willst, ist eine Basisklasse, deren Spezialisierungen die Details dann unterschiedlich umsetzen.

Oder eben eien Klasse die einige Parameter hat, dann hättest Du verschiedene Objekte der gleichen Klasse. Hier kannst Du dann extrem einfach einen typisierten Pointer nehmen, weil es nur einen Typ gibt, bei Vererbung etc. mußt Du ein wenig aufpassen und ggf. dann doch wieder casten (Oder eben auf Virtuals - Polymorphie setzen).


freakyGTA 
Fragesteller
 08.10.2018, 21:53

Der eigentliche Grund wieso ich eigene Klassen dafür will ist, da ich in der vorherigen Version etliche Variablen in einer Klasse hatte die ja dieselbe Funktion haben, aber halt andere Werte da sie für einen anderen Modus sind. Das fande ich nicht so schön und sehr unübersichtlich.

Jetzt als ich deine Antwort gelesen habe, sind mir namespaces wieder in den Sinn gekommen.

Dann müsste ich zwar bei Update() und getPause() wieder abfragen welcher Modus den gerade an ist, aber es wäre bestimmt übersichtlicher.

Hier sind mal zwei Modis in ihren Klassen. Je nach Art des Moduses können diese halt umfangreicher sein. Die zwei sind ganz simple.

https://paste.ofcode.org/554KzwihawJKxdGsnLsJQd

Was hältst du von der Idee mit den namespaces und weißt du eine "elegantere" Lösung?

0
KarlRanseierIII  08.10.2018, 22:03
@freakyGTA

Humm, ohne Gesamtkonzept ist es immer schwer qualifizierte Antworten zu geben.

Du kannst natürlich für jeden Modus eine eigenen Klasse machen, wenn es kaum Gemeinsamkeiten gibt.

Ich vermute, es kann ohnehin immer nur ein Modus gleichzeitig Verwendung finden? Dann wäre natürlich ein Pointer mit Cast tatsächlich eine Option.

Eine abstrakte Basisklasse mit Polymorphie ist aber auch von der Codelesbarkeit her deutlich eleganter.

2
freakyGTA 
Fragesteller
 08.10.2018, 22:16
@KarlRanseierIII

Ich wollte jetzt nicht unbedingt einen großen Text schreiben, da mit das schnell passiert wenn ich was erklären will :'D Ich kann ja mal versuchen das möglichst kurz zu erklären oder den ganzen Code posten? Dieser ist aber nur teils fertig, da ich ja nicht weiter komme und solange ich nicht weiß, wie ich das mit den Modis regle, kann ich ab einem bestimmten Punkt den Rest nicht machen.

Ja, Gemeinsamkeiten gibt es kaum.

Genau. Es gibt einmal den Modus der über Musikbeleuchtung, "Idle"-Beleuchtung und Ambilight (kommt hinzu wenn der Rest läuft) entscheidet. Dann gibt es die (ich nenne sie mal) Submodes um die es mir gerade geht. Und davon kann und soll immer nur eines aktiv sein. Ich probiere es mal aus was auf den Pointer zu casten und ob ich dann auf die Funktionen zugreifen kann.

Das sollte ich mir vielleicht auch mal anschauen

0
freakyGTA 
Fragesteller
 08.10.2018, 22:22
@freakyGTA

Zwei Minuten googeln nach virtuellen Methoden und ich habe genau das gefunden was ich brauche. Vielen Dank! :)

0
KarlRanseierIII  08.10.2018, 22:26
@freakyGTA

Die Sache ist eben folgende:

Nehmen wir an, Du hast einen void *. Nun wird Deine Klasse für Modus a gewählt und instanziiert. Die Adresse kannst du dem Voidpointer zuweisen. Soweit so einfach.

Wenn Du nun eine Methode aufrufen willst, muß der Pointer aber typisiert sein, also mußt Du ihn abhängig vom Modus casten. Und das bei jedem Methodenaufruf - Kann man natürlich machen, ist aber etwas ekelig. (Du mußt dann nämlich immer eine Fallunterschiedung machen.)

Erzeugst Du nun eine abstrakte Basisklasse, die nur virtuals der Methoden enthält, wobei die anderen Klassen von dieser erben, kannst Du sie instanziieren und einen Pointer vom Typ der Baisklasse nehmen, um 'typenneutral' auf die Instanz zuzugreifen.

In C gab es für solche multi-type-single-name-Zaubereien die Union - Sieht man bei Socketprogrammierung z.B. .

0
freakyGTA 
Fragesteller
 08.10.2018, 22:31
@KarlRanseierIII

Ja da hast du Recht. Erscheint mir mittlerweile auch als die beste und schönste Lösung.

Ich beschäftige mich ja schon länger mit programmieren. Aber nie lange, da mich dann immer wieder was interessiert hat und ich dann wieder alles vergessen habe.

Jetzt beschäftige ich mich seit ein paar Wochen intensiv damit und bin immer wieder fasziniert davon was es zwischen der und der Art ein Problem zu lösen für Unterschiede und Ansätze gibt. Einfach unglaublich. Das freut mich irgendwie :D

0
Schwarzlicht42  08.10.2018, 22:37

"Pointer in C++ sind solange 'pfui' solange Du die einzelnen Objektinstanzen nicht dynamisch auf dem Heap erzeugen mußt oder willst." - das stimmt. Und wenn man in C++ das RAII Pattern durchzieht, braucht man fast nie einen Pointer.

Wenn du Objekte auf dem Heap erzeugen willst, kannst du einen auto_ptr nehmen, wenn es mehrere sein sollen std::vector<Objekt> und selbst wenn man mit einer C-Schnittstellt spricht, die z.B. einen char* zurückliefert, macht man sich einen std::vector<char> in der entsprechenden Puffergröße und gibt std::vector::data() an die C-Funktion. So kann man gut Memory-Leaks vorbeugen...

0

"Jetzt habe ich was von void Zeigern gelesen. Dass man den Datentyp diese Variable jederzeit ändern kann. Was ich jetzt nur nicht verstehe, wenn ich diesen void-Zeiger jetzt mit eine der Klassen "befülle", wie kann ich dann auf Funktionen dieser Klasse zugreifen um z.B. den Frame zu updaten oder die Pausenzeit usw abzufragen?" - du müsstest den Zeiger in den Typ deiner Klasse casten. Ungefähr so:

void* zeiger = new DeineKlasse();

(DeineKlasse)zeiger->funktionXY();

oder besser:

DeineKlasse* zeigerspeziell = dynamic_cast<DeineKlasse>(zeiger);

if (zeigerspeziell) // das ist der Check, ob das casten geklappt hat

{

zeigerspeziell->funktionXY;

}

Aber nimm lieber den Ansatz von J0T4T4, da void-Zeiger aus der Zeit vor der Objektorientierung stammt, als reines C ohne ++ keinen Polymorphismus kannte! ;)