Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

1

02.04.2016, 03:19

Einen Datentypen auf eine Referenz casten

Hi,
erstmal sorry, mir viel kein deskriptiverer Titel ein. Sollte jemand diesbezüglich eine Idee haben, dann bitte ich den Mod/Admin dies entsprechend zu ändern.
Ich habe folgenden Code:

C-/C++-Quelltext

1
2
3
4
5
    struct NativeHandle; // Wird nirgendswo definiert; genauso gut könntest dass auch 'typedef void* NativeHandle;' heißen.

    const NativeHandle& Impl::getNativeHandle() const{
        return (NativeHandle&) handle;
    }


Ich bin mir nicht sicher, ob bei C++ Referenzen genauso wie Pointer behandelt werden.
Darf ich meine Logik wie im vorangegangenem Snippet definieren oder muss ich systemabhängige Datentypen anders abstrahieren? (Kommt es hier zu Problemen/undefiniertem Verhalten?)
Ich gehe hierbei aus, dass jemand, der 'getNativeHandle()' verwendet, weiß zu welchem Datentype er casten muss.

LG Julien
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

02.04.2016, 10:58

Casten kannst du immer, aber erstens solltest Du dynamic_cast verwenden und zweitens ist die Annahme, dass der User weiß, was er für einen Datentypen braucht, sehr sehr schlecht. Das kannst Du bestimmt mit anderen Mitteln besser lösen. Daher die Frage: Wieso musst Du da überhaupt casten, was hast Du da gebaut?
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

3

02.04.2016, 12:27

Wenn das C++ ist, ist das Quatsch. Je nach Rückgabetyp der Funktion wird automatisch entweder eine Kopie des Handles oder eine Referenz auf das Handle zurückgegeben. In beiden Fällen schreibst Du schlicht

C-/C++-Quelltext

1
return handle;
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

CeDoMain

Alter Hase

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

4

02.04.2016, 16:09

Ich stimme meinen beiden Vorrednern zu! Schreib mal wozu du das brauchst. Soll das vielleicht ein Singleton werden? :D

Ansonsten speicher einfach direkt einen Zeiger mit dem Typ NativeHandle in deiner Klasse oder wo auch immer. Wenn das nur ein Getter (wie in Java z.B.) für das Feld sein soll, dann vergiss das - in C++ brauchst du sowas nicht.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

5

02.04.2016, 19:26

'NativeHandle' ist an sich keine Klasse. Es ist eigentlich ein "Opaque Pointer" wie man es aus C und GTK+ kennt, nur mit einer Referenz statt einem Pointer,
damit möchte ich verhindern, dass jemand 'delete' aufruft. Verschiedene Betriebssysteme bieten verschiedene Datentypen als 'Handle' an;
meist ein primitiver Datentyp oder eine Struktur -> Abstraktion über 'NativeHandle'.

@BlueCobold: Könntest du mir ein Tipp geben, was die bessere Methode denn sei?
Mir ist leider noch kein sauberer Weg bekannt. Was 'dynamic_cast' betrifft, werde ich wohl leider
verzichten müssen. Die Klasse selber befindet sich in einer '.so'-Datei (für die Windowsnutzer: '.dll'),
weswegen ich mich nicht auf RTTI verlassen kann.

Ich frage mich nur, ob eine Referenz genauso wie ein Zeiger behandelt wird und nur die Adresse des Speicherbereiches drinnen gespeichert wird.
LG Julien
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

02.04.2016, 19:54

Wenn es um verschiedene Systeme geht, würde ich ehrlich gesagt im Header per #ifdef das System prüfen und für jedes den passenden Datentyp definieren. So ist man immer typesafe.

Dass jemand delete auf einem Pointer aufruft, der ihm nicht gehört, ist eine Sache, die Du nicht berücksichtigen solltest. Man kann schließlich auch eine Referenz in einen Pointer wandeln und dann deleten. Entsprechende Crashes durch falsche Handhabung des Nutzers liegen nicht in Deiner Verantwortung.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

7

03.04.2016, 12:46

Ich frage mich nur, ob eine Referenz genauso wie ein Zeiger behandelt wird und nur die Adresse des Speicherbereiches drinnen gespeichert wird.


Ja, intern nimmt der Compiler immer Zeiger für Referenzen. Das sollte Dir aber egal sein, weil Du als Programmierer auf ner höheren Ebene arbeitest, wo Du halt eine Referenz in der Hand hast. Stell Dir Referenzen und Zeiger wie einen Griff vor. Du hast nicht die Kiste selbst in der Hand, sondern ziehst nur am Griff der Kiste. Alle Leute, die an dem Griff zufassen, haben die selbe Kiste in der Hand.

Dass jemand dann den Zeiger von der Kiste nimmt und delete darauf anwendet, hast Du nicht in der Hand. Du solltest in Deiner API nur die Dummheiten verhindern, die durch idiomatischen (== normalen, nicht böswilligen) Gebrauch der API entstehen können. Alles Andere kannst Du nicht verhindern, aber Du bist auch im moralischen Sinne nicht mehr Schuld an den Auswirkungen.

Und am Thema vorbei: Du baust eine DLL oder SO. Hm. Weißt Du, dass diese SO dann nur mit genau dem Compiler und den Einstellungen benutzbar ist, mit denen die SO auch gebaut wurde? Der ganze Kram um Name Mangeling usw. ist in C++ nicht standardisiert, also wirst Du schon bei kleinsten Abweichungen der Compilereinstellungen absurde DynamicLoad-Fehler kriegen. Die DLL an andere Programmierer und Projekte weiterzureichen ist mehr oder minder ausgeschlossen. Meine Empfehlung: bau den Source mit, linke statisch.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

Julién

Alter Hase

  • »Julién« ist der Autor dieses Themas

Beiträge: 717

Wohnort: Bayreuth

Beruf: Student | Hilfswissenschaftler in der Robotik

  • Private Nachricht senden

8

03.04.2016, 15:28

@BlueCobold: Ich verwende das PIMPL-Idiom, damit ich keine Abhängigkeiten zu SDK's habe, die nicht bereits im 'includePath' sind.

@Schrompf: Das war mir erst gar nicht bewusst. Wie steht's eigentlich mit 'dlsym'. Kann ich Funktionen aus '.so'-Dateien laden (und benutzen) auch wenn diese z.B. mit clang kompiliert wurden, statt mit GCC?
I write my own game engines because if I'm going to live in buggy crappy filth, I want it to me my own - Ron Gilbert

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

9

03.04.2016, 17:41

@Schrompf: Das war mir erst gar nicht bewusst. Wie steht's eigentlich mit 'dlsym'. Kann ich Funktionen aus '.so'-Dateien laden (und benutzen) auch wenn diese z.B. mit clang kompiliert wurden, statt mit GCC?


Nein. Die Schnittstelle muss nur C sein, nur dann geht das. Und auch dann kann es scherbeln, wenn Du z.b. in der SO Speicher allokierst und zurückgibt, um ihn dann draußen freizugeben.

Wie gesagt: bau keine SO. Das bringt außerhalb von irgendnem Plugin-System genau gar nix, kostet aber Performance, macht das Leben mühsamer und bietet fünf Millionen Möglichkeiten für Crashes oder subtile Fehlverhalten.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

10

03.04.2016, 18:15

@BlueCobold: Könntest du mir ein Tipp geben, was die bessere Methode denn sei?
Mir ist leider noch kein sauberer Weg bekannt. Was 'dynamic_cast' betrifft, werde ich wohl leider
verzichten müssen. Die Klasse selber befindet sich in einer '.so'-Datei (für die Windowsnutzer: '.dll'),
weswegen ich mich nicht auf RTTI verlassen kann.

Ich versteh zwar nicht ganz, wieso genau die DLL dir RTTI verbietet, aber dynamic_cast ist in der Regel eine ganz schlechte Idee...

Die richtige Lösung wurde ja schon genannt: Wenn jemand delete auf etwas aufruft, das ihm nicht gehört, ist er selber schuld.


Ich frage mich nur, ob eine Referenz genauso wie ein Zeiger behandelt wird und nur die Adresse des Speicherbereiches drinnen gespeichert wird.

Konzeptionell sind Referenzen keine eigenständigen Objekte, sondern repräsentieren direkt das referenzierte Objekt; der Compiler wird Referenzen oft aber als Adresse des referenzierten Objektes umsetzen...

Werbeanzeige