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

1

14.04.2009, 00:17

conversion operator

Also ich möchte ein ProxyObj<WorldObject> in ein ProxyObj<Character> casten können.
Da man conversion operatoren scheinbar immer als Member deklarieren muss und man keinen Rückgabewert oder Parameter definieren kann, schien mir das so direkt kaum Möglich zu sein (da ich ja nur ein ganze bestimmtes ProxyObjekt in ein ganz bestimmtes anderes casten können will).
Also hab ich das noch einmal abgeleitet um das ein wenig zu spezialisieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
template <typename t> class ProxyObj
{
public:
    ProxyObj(t** Obj):
    m_Obj(Obj)
    {
    }
    ProxyObj(ProxyObj<t>& Ref):
    m_Obj(Ref.Obj)
    {
    }
    bool IsValid()
    {
        return (*m_Obj)!=NULL;
    }
    t* operator->()
    {
        return *m_Obj;
    }
    t* operator*()
    {
        return *m_Obj;
    }
protected:
    t **m_Obj;
};


typedef ProxyObj<Character> CharacterRef;


class WorldObjectRef : public ProxyObj<WorldObject>
{
public:
    WorldObjectRef(WorldObjectRef &Obj):
        ProxyObj<WorldObject>(Obj)
    {
    }

    WorldObjectRef(WorldObject** Obj):
        ProxyObj<WorldObject>(Obj)
    {
    }

    operator CharacterRef ()
    {
        return CharacterRef(reinterpret_cast<Character**>(m_Obj));
    }
}


Jetzt kommt beim return allerdings der Fehler:
|error: no matching function for call to `ProxyObj<Character>::ProxyObj(CharacterRef)'|
Und er schlägt mir die beiden ProxyObj Konstruktoren vor. Meiner Meinung nach müsste der Typ aber stimmen.
Lieber dumm fragen, als dumm bleiben!

2

14.04.2009, 00:53

Re: conversion operator

Zitat von »"Jonathan_Klein"«

Also ich möchte ein ProxyObj<WorldObject> in ein ProxyObj<Character> casten können.
Dafür scheint mir deine Vorgehensweise etwas sehr frickelig. Vererbung ist hier nicht der richtige Ansatz. Denn abgesehen davon, dass Vererbung zu viel Aufwand für nur einen Fall wäre, vergisst du eines: Nicht jedes ProxyObj<WorldObject> ist auch ein WorldObjectRef.

Du willst aber Templates mit unterschiedlichen Instanziierungen zueinander casten. Da wäre es doch einfacher, du hättest eine Funktion:

C-/C++-Quelltext

1
ProxyObj<Character> ToCharacterProxyObj(const ProxyObj<WorldObject>&);

Auch dein reinterpret_cast scheint auf einen Designfehler hinzuweisen. Zudem ist er sehr fehleranfällig, in den meisten Fällen wird so ein brutaler Cast zwischen unterschiedlichen Klassen zu Laufzeitfehlern führen. Den reinterpret_cast-Operator braucht man normalerweise nur im Zusammenhang mit Low-Level-Speicherzugriffen. Falls die beiden Klassen zueinander kompatibel sind, stehen sie entweder in einer Hierarchie, oder es existieren entsprechende Konvertierungsfunktionen.

Wozu hast du überhaupt einen Doppelzeiger? Auch das ist sehr selten, gerade wenn man Container zur Speicherverwaltung einsetzt.

3

14.04.2009, 01:01

Re: conversion operator

Zitat von »"Nexus"«


Vererbung ist hier nicht der richtige Ansatz. Denn abgesehen davon, dass Vererbung zu viel Aufwand für nur einen Fall wäre, vergisst du eines: Nicht jedes ProxyObj<WorldObject> ist auch ein WorldObjectRef.

Ja, das stimmt, aber da ich sonst eh ein typedef schreiben würde, wäre das kein Problem.

Und wenn ich eine cast Funktion schreibe, nun dann müsste die auf private Member zugreifen. Ich könnte das evtl. mit friend umgehen, aber besonder toll finde ich das auch nicht.

Character ist btw. von World Object abgeleitet und den reinterpret_cast hab ich, da weder static noch dynamic cast gehen wollte und ich nicht unbedingt einen C Cast machen wollte.

Aber selbst wenn ich das alles irgendwie umgehen könnte, wäre es interessant, was mit den Typen da nicht stimmen soll.
Lieber dumm fragen, als dumm bleiben!

4

14.04.2009, 01:08

Re: conversion operator

Zitat von »"Jonathan_Klein"«

Ja, das stimmt, aber da ich sonst eh ein typedef schreiben würde, wäre das kein Problem.
Auch ein typedef würde da nicht helfen. Du dürftest keine Instanzen mehr von ProxyObj<WorldObject> haben, sondern nur noch die der abgeleiteten Klasse WorldObjectRef.

Zitat von »"Jonathan_Klein"«

Und wenn ich eine cast Funktion schreibe, nun dann müsste die auf private Member zugreifen. Ich könnte das evtl. mit friend umgehen, aber besonder toll finde ich das auch nicht.
Dann biete doch entsprechende Getter und Setter an. Das ist immer noch viel sauberer als den Umweg über eine konzeptbrechende Vererbung. Selbst friend wäre noch sauberer.

Zitat von »"Jonathan_Klein"«

Character ist btw. von World Object abgeleitet und den reinterpret_cast hab ich, da weder static noch dynamic cast gehen wollte und ich nicht unbedingt einen C Cast machen wollte.
Casts zwischen verwandten Klassentypen funktionieren nur bei einer Referenz oder einem Zeiger, was auch sinnvoll ist. Also warum brauchst du jetzt die Doppelzeiger (du hast wahrscheinlich mein letztes Edit nicht mehr gesehen)?

Zitat von »"Jonathan_Klein"«

Aber selbst wenn ich das alles irgendwie umgehen könnte, wäre es interessant, was mit den Typen da nicht stimmen soll.
Hm, der scheint zu stimmen. Ich kann dir da auch nicht gerade helfen, bist du sicher, dass das den Fehler ausgelöst hat?

5

14.04.2009, 07:23

Re: conversion operator

Zitat von »"Nexus"«

Wozu hast du überhaupt einen Doppelzeiger? Auch das ist sehr selten, gerade wenn man Container zur Speicherverwaltung einsetzt.

Damit ich z.B. den ersten Zeiger auf NULL setzen kann, falls da Objekt gelöscht wird und somit direkt sämtliche ProxyObjekte wissen, dass das, worauf sie zeigen, ungültig geworden ist.

Zitat von »"Nexus"«


Auch ein typedef würde da nicht helfen. Du dürftest keine Instanzen mehr von ProxyObj<WorldObject> haben, sondern nur noch die der abgeleiteten Klasse WorldObjectRef.

Nein, ich meine, ich werde eh nie ein ProxyObj<World> verwenden, sondern habe nur vor WorldObjRef und CharacterRef zu verwenden. Ob das jetzt ein typedef oder eine eigene Klasse ist, ist mir da relativ egal. Von daher sollte es da also keine Probleme geben.

Zitat von »"Nexus"«


Ich kann dir da auch nicht gerade helfen, bist du sicher, dass das den Fehler ausgelöst hat?

Hm, nicht so ganz, aber er meckert wegen dem Typ und das ist der einzige Fehler, den ich weit und breit habe.

[edit]
Hm, Problem gelöst. Ich äh, habe scheinbar den Kopierkonstruktor in ProxyObj falsch deklariert, da fehlte scheinbar ein const. Er konnte das Objekt dann scheinbar zwar korrekt erstellen, aber nicht returnen.

Und wo wir gerade schon beim casten sind: Wäre operator bool() das Mittel der Wahl, wenn man haben möchte:

C-/C++-Quelltext

1
2
3
4
if(MyObj)
{
//Objekt ist gültig, oder nicht leer, oder sonst was

}

?
[/edit]
Lieber dumm fragen, als dumm bleiben!

6

14.04.2009, 12:22

Re: conversion operator

Zitat von »"Jonathan_Klein"«

Und wo wir gerade schon beim casten sind: Wäre operator bool() das Mittel der Wahl, wenn man haben möchte:

ja, die streambiliothek machts ja auch so ;)

Fred

Supermoderator

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

7

14.04.2009, 12:32

Ich würde dir auch dringend empfehlen das ganze über eine entsprechenede Cast-Funktion zu regeln. Die Membervariablen veränderst du durch set-Methoden und schon geht das ganze sehr sauber von der Hand. Denn die Lösung, die du momentan hast, würde ich als äußerst unsicher beschreiben und sie ist sicher alles andere als optimal.

8

14.04.2009, 14:15

Re: conversion operator

Zitat

Damit ich z.B. den ersten Zeiger auf NULL setzen kann, falls da Objekt gelöscht wird und somit direkt sämtliche ProxyObjekte wissen, dass das, worauf sie zeigen, ungültig geworden ist.
Das verstehe ich jetzt nicht ganz. Wozu überhaupt zwei Zeiger, geht das Ungültig-Machen nicht mit einem? Willst du mehrere Objekte darin speichern? Falls ja, würde ich zu Containern raten. Ansonsten scheint mir kein Grund für Doppelzeiger einzufallen.

Zitat von »"PCShadow"«

ja, die streambiliothek machts ja auch so ;)
Nein, macht sie nicht. -> Safe Bool Idiom

Zitat von »"Fred"«

Ich würde dir auch dringend empfehlen das ganze über eine entsprechenede Cast-Funktion zu regeln. Die Membervariablen veränderst du durch set-Methoden und schon geht das ganze sehr sauber von der Hand. Denn die Lösung, die du momentan hast, würde ich als äußerst unsicher beschreiben und sie ist sicher alles andere als optimal.
Dem stimme ich vollständig zu. Ich würde mir das wirklich nochmals überlegen. Auch wenn es momentan funktioniert, ist es alles andere als schön und unnötig kompliziert. Und mit dem reinterpret_cast auch noch zusätzlich fehleranfällig...

9

14.04.2009, 14:57

Es ging ja nur ums Prinzip, ich könnte ja ohne weiteres noch eine Prüfung einbauen. Es ist ja keine allgemeine Klasse, sondern nur ein Template, damit ich keine 3 quasi identischen Klassen schreiben muss, für was anderes soll und wird es nie benutzt werden.
Und: Wie sonst soll ich casten? Mit C-Casts?

Nochmal zur Erläuterung des Doppelzeigers.
Ich habe ein großes Objekt, das an verschiedenen Stellen Verwendung findet. Also würde ich jetzt per Zeiger darauf zugreifen. Nun will ich es aber löschen und alle die einen Zeiger darauf haben, sollen testen können ob es das Objekt noch gibt, was so aber nicht geht.
Also habe ich einen Doppelzeiger, alle Objekte kriegen nur den Zeiger auf den Zeiger. Jetzt kann ich also den Zeiger auf das Objekt auf 0 setzen wenn das Objekt gelöscht wird und die Benutzer haben jetzt einen Zeiger auf einen Zeiger der 0 ist und sehen damit genau, dass das Objekt nicht mehr gültig ist.
Lieber dumm fragen, als dumm bleiben!

10

14.04.2009, 15:07

Das scheint mir so, als wäre hier ein shared_ptr angebracht. Bei diesem Smart Pointer wird der Besitz des Objekts unter verschiedenen shared_ptr-Instanzen geteilt. Sobald keine Instanz mehr auf das Objekt zeigt, wird der Speicher freigegeben, du brauchst dich um nichts zu kümmern.

Eine kleine Einführung findest du hier...

Werbeanzeige