Ressourcen entpacken
-
WebFritzi schrieb:
Also, wenn du mir das nicht begründen kannst, sehe ich das nicht ein.
Ein paar einfache Gründe: Casts sind in vielen Fällen unnötig und blähen den Code übermäßig auf, wo es gar nicht nötig wäre. Zudem kann insbesondere der C-Cast, da er kontextsensitiv ist, je nach Fall ein static_cast, ein const_cast, ein reinterpret_cast oder gar mehrere zugleich sein - oft, obwohl man eigentlich nur einen static_cast oder implicit_cast wollte. => static_cast verwenden oder - wenn nicht nötig - gar nicht casten. Ein gutes C++-Programm sollte eigentlich mehrheitlich ohne Casts auskommen.
In diesem speziellen Fall halte ich den Cast allerdings - sofern du ihn als static_cast schreibst
- für vertretbar. Casten zwischen Handles ist, auch wenn es hier laut windows.h ausdrücklich nicht nötig ist, für gewöhnlich unerläßlich. Wer es nicht glaubt, definiere in den Compileroptionen mal das Präprozessorsymbol "STRICT". Und das hat auch fast immer seinen Grund - Handles sind wie Zeiger auf polymorphe Datentypen zu behandeln, und zwischen denen castet man ja auch nicht ohne weiteres herum.
-
@WebFritzi: Also böse gesagt ist das ja dann möglicherweise eher Dein Problem, wenn Du es nicht einsiehst (da Du ja dann später die Probleme bekommen könntest). Aber okay, das mal hier als Beispiel (wobei dieses Beispiel bewusst übertreibt):
short __stdcall DlgProc(HINSTANCE hDlg, UINT uiMessage, unsigned short wParam, unsigned short lParam) { // ... }So, wie man sieht ist diese Dlg-Proc ist vollkommen falsch
.
Wenn Du diese dann aber so verwendest, sollte es keinen Compiler-Fehler geben:DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(DLG_MAIN), (DLGPROC)DlgProc);
-
WebFritzi schrieb:
Ich hasse Dogmen! Also, wenn du mir das nicht begründen kannst, sehe ich das nicht ein.
Ein cast kaschiert die falsche Nutzung einer Variablen. Typenkonforme Verwendung erlaubt es dem Programmierer sich etwas mehr auf den Compiler zu verlassen.
1. Also nehmen wir mal an, Du hast eine Variable von Typ1 und die castest überflüssiger Weise auch auf Typ1, dazu noch mit einem "verabscheuungswürdigen" C-cast, der einem Dampfhammer gleichkommt und Du änderst in der Eveolution Deines Programmes nun die Variable auf Typ2, dann wird der Compiler Dir nicht helfen können und Dein Programm wird evtl. übelst abrauchen.
2. Ein C++ cast static_cast, dynamic_cast ist da weitaus intelligenter und wenn man schon castet vorzuziehen! Er schützt einen wenigstens gegen einige falsche Verwendungen!
3. Es macht ein Programm unlesbar.
4. Es irritiert. Ein weitere Progranmmierer wie ich aus Deinen Team, wird sich denken: "Warum castst er hier" oh muss ein Schweinecode Trick sein, bis er merkt, dass es ein noop ist.Just my 2 cents!
-
Sehe ich das richtig, dass ein C-Cast
Typ1 a; Typ2 b = (Typ2)a;folgendes macht:
Typ1 a; Typ2 b = *((Typ2*)&a);??? Wenn ja, sehe ich nicht,w as daran verwerflich sein sollte, solange ich weiß, was im Speicher vor sich geht.
-
WebFritzi schrieb:
Sehe ich das richtig, dass ein C-Cast folgendes macht:
Nicht ganz. Wie ich bereits schrieb, tut er, je nach Kontext, das, was static_cast, reinterpret_cast oder const_cast machen:
int i = 1; const char* s = "ein String"; double f = (double) i; // entspricht static_cast <double> (i) int* pi = (int*) &f; // entspricht reinterpret_cast <int*> (&f) char* s2 = (char*) s; // entspricht const_cast <char*> (s)Mit dem C++-Cast ist es also möglich, eine bestimmte Cast-Art zu erzwingen, wodurch er wesentlich differenzierter eingesetzt werden kann - man sieht z.B. an der Verwendung eines reinterpret_cast zumeist, daß es sich um implementierungsabhängige Operationen handelt, am static_cast, daß eine gewöhnliche, recht harmlose Castoperation vorliegt und am const_cast, daß entweder der Programmierer Designfehler eingebaut oder mit solchen umzugehen hat.
WebFritzi schrieb:
Wenn ja, sehe ich nicht,w as daran verwerflich sein sollte, solange ich weiß, was im Speicher vor sich geht.
Es ist genausowenig verwerflich, globale Variablen, öffentliche Member, Makros etc. zu verwenden, wenn man genau weiß, was vor sich geht. Das ändert nichts an der Tatsache, daß all diese Dinge, Casts und insbesondere C-Casts eingeschlossen, Code unübersichtlicher machen, die Wartung des Codes durch Dritte (oder durch dich selbst nach zu langer Zeit) erschweren, schwer auffindbare Fehler und Bugs hervorrufen, bei der Portierung eines Programmes unerklärlicherweise fehlschlagen.
-
Ich kan dem was audacia geschrieben hat nur zu 100% zustimmen.
Per Definition sind C casts in unserer Firma untersagt.
-
@audacia: Vielen Dank für deine ausführliche Erklärung. Entspricht dann
Typ2 b = reinterpret_cast<Typ2>(a);dem hier:
Typ2 b = *(Typ2*)&a;???
Und was ist das Verhalten von dynamic_cast in der Dprache der C-Casts?
-
WebFritzi schrieb:
was ist das Verhalten von dynamic_cast in der Dprache der C-Casts?
Einen dynamic_cast gibt es in C (logischerweise) nicht, da der für polymorphe Objekte (Typen) ist (
C++, Stichwort: RTTI). Du kannst zwar auch einen C-Cast (Type) verwenden, aber da gibt es keine Prüfung zur Laufzeit, ob der Cast erfolgreich ist.
Scheiße
. Dieser wird verwendet um in Klassenhierarchien sichere (also kontrollierte) Downcasts durchzuführen.EDIT: Quote gefixt.
-
Ah, danke.

-
leuts, wo ihr schonmal dabei seid das thema so auszubreiten, ich will nochne .dll mitlinken (das ist ja net das prob) sondern das laden, wie soll das gehen (also von der .dll aus ressourcen)
also wenn die .dll die ich brauche net im selben ordner oder in system32 liegt kanns prog net gestartet werden.
also geht das überhaupt? wenn ja, wie?
-
Du könntest der DLL die HINSTANCE mitgeben. Das ist ja alles, was man braucht, um Resourcen zu laden.
-
Ich weiss ja nicht wie das geht, zum 3ten oder 4ten mal hier, ich habe von winapi fast keine ahnung, fenster und buttons bekomme ich hin und winsock, das wars auchschon...
nen kleiner code snippet wäre hilfreich
mfg
-
WebFritzi schrieb:
Entspricht dann
Typ2 b = reinterpret_cast<Typ2>(a);dem hier:
Typ2 b = *(Typ2*)&a;???
Ebenfalls nicht ganz. Der reinterpret_cast achtet darauf, daß die Typen, auch wenn ihm die Konvertierung mißfällt, zumindest die gleiche Größe haben, was du mit dem Zeigercast umgehst. Dadurch sind auch Dinge möglich wie
int i; double pd = *((double*) &i);. Mit einem direkten reinterpret_cast geht das nicht (der Zeiger läßt sich allerdings ebenso reinterpret_casten).
-
Martin Richter schrieb:
Erst LockResource mapped den entsprechenden Speicher ein. Wenn Du wenig Resourcen hast, sind die Seiten bereits im Speicher. Werden diese jedoch größer ist das nicht gewährleistet.
Nein, LockResource sieht in Win32 so aus:
PVOID LockResource(HGLOBAL hGlob) { return (PVOID) hGlob; }