Zeiger zeigt auf konstanten Zeiger...
-
ceplusplus@loggedoff schrieb:
Achsooooo, ich dachte b zeigt dann auf a, und durch b könnte ich a verändern! Habs jetzt wohl verstanden, b zeigt dann auf die Adresse von a, in welcher doch das Objekt HWND__ abgelegt ist...
Nun, jetzt würd ich noch gern wissen, was es mit den typdefs auf sich hat.
typedef int T; //T ist ein int. const T x; // ? == const int bzw. int const , tut sich nix T const x; // ? == const int bzw. int const , tut sich nixtypedef int* T; // T ist ein Zeiger auf ein nichtkonstantes int const T x; // ? // T ist konstant, also ein konstanter T const x; // ? // Zeiger auf ein nichtkonstantes int, in BEIDEN Faellenin der vorletzten Zeile steh const T, wenn man den typedef einfach wie ein Makro ersetzen wuerde, stuende dort const int* x; was ein Zeiger auf ein const int waere - tatsaechlich handelt es sich aber auf einen const Zeiger auf ein nonconst int. Aus dem Grund ist es oft ueblich, das const immer rechts con dem Zu schreiben, worauf es sich bezieht:
int* const; //pointer ist const, int nicht int const*; //int ist const, pointer nicht T const&; //Referenz auf ein const T T const; //auch typedefs kann man so einfach einsetzen
-
const int* x; // veränderbarer Zeiger auf konstantes int int const* x; // veränderbarer Zeiger auf konstantes int const* int x; // konstanter Zeiger auf veränderbares int ? int* const x; // konstanter Zeiger auf veränderbares intStimmt das nun so? Besonders die vorletzte Zeile.
Und wie schaffe ich es nun, dieses Objekt...
HWND windowHandle;
...per Funktion so zurückzugeben, dass von mir aus der Zeiger, nicht aber das Objekt veränderbar ist?
MfG
-
const* int x; // konstanter Zeiger auf veränderbares int ?Dies ist ein Syntaxfehler, zuerst muß immer der Datentyp kommen, danach erst die Sternchen (Zeiger).
Was in deiner Auflistung noch fehlt, ist:
int const * const x; // konstanter Zeiger auf konstantes int const int * const x; // konstanter Zeiger auf konstantes intWie du siehst, kann man bei dem Datentypen das 'const' vorher oder nachher schreiben, aber beim Zeiger muß 'const' immer nachher stehen (oder alternativ bzw. zusätzlich noch volatile - aber hier gehe ich jetzt nicht weiter drauf ein).
Daher bevorzugen viele C/C++ Programmierer die erste Schreibweise, da die zweite quasi unsymmetrisch ist (und wie in deinem Fall zu dieser Frage führt).
Und die Zeiger-Schachtelung kann sogar noch weiter gehen (int [const] * [const] * [const] * ...). Ich meine, ein Standard-Compiler muß mindestens 5 Indirektionen unterstützen...
-
Jo danke, ich denke ich hab alles verstanden. Wusste ned, dass von rechts nach links zusammengefasst wird.
Nun, eine Frage bleibt noch offen:
Wie schaffe ich es nun, dieses Objekt...
HWND windowHandle;
...per Funktion so zurückzugeben, dass das Objekt nicht veränderbar ist?
MfG
-
Ein Windows-Handle ist intern einfach nur ein void * (bzw. im Modus 'STRICT' wird jeder Handletyp als Zeiger auf eine eigene Struktur angelegt, die aber nicht genutzt wird).
Also du kannst ein HWND nicht so als konstant deklarieren, daß das Objekt selber nicht verändert werden kann (dies würde also einem "void * const" entsprechen, jedoch könntest du damit dann keine WinAPI-Funktion mehr aufrufen - denn diese Funktionen können nur "void *" akzeptieren).
Was wolltest du denn damit überhaupt unterbinden?
-
Achsoo, naja es ist so:
Meine Window-Klasse soll das Fensterhandle zurückgeben können:HWND Window::getWindowHandle() { return windowHandle; }Damit dann eine weitere Klasse damit initialisiert werden kann:
void Bla::Initiate(HWND windowHandle) { ... }Ich wollte es halt schön sauber haben, sodass das Handle, welches per getWindowHandle() zurückgegeben wird, niemals verändert werden kann.
Weiß nur nicht, wie ich das mache, ohne windowHandle in der Window-Klasse als const zu definieren.
MfG
-
ceplusplus@loggedoff schrieb:
Ich wollte es halt schön sauber haben, sodass das Handle, welches per getWindowHandle() zurückgegeben wird, niemals verändert werden kann.
Es kann doch gar nicht verändert werden, höchstens das Fenster dahinter. Wenn jemand in der Initiate-Funktion "windowHandle=xyz" schreibt, beeinflusst das das ursprüngliche Handle ja nicht, nur die lokale Variable. Du kannst halt nur nicht verhindern, dass das Handle in einer DestroyWindow-Funktion o.ä. eingesetzt wird, das verhindert (leider) das Konzept der WinAPI.
-
Eben, das Fenster. Sollte es aber nicht... Das Fenster sollte nur durch die Window-Klasse verändert werden können.
Aber... Die lokale Variable ist doch ein Zeiger auf das windowHandle-Objekt in der Window-Klasse?!
bla.Initiate(window.getWindowHandle());Hier wird doch der Zeiger, welcher von getWindowHandle() zurückgegeben wird, in die lokale Zeigervariable der Funktion Initiate() kopiert, die lokale Zeigervariable zeigt dann also auf das windowHandle-Objekt in der Window-Klasse?!
Also würde dann ein windowHandle=xyz in der Initiate-Funktion das Objekt in der Window-Klasse verändern, welches Objekt denn sonst? Ist ja nur das eine vorhanden, ansonsten nur zwei Zeiger...
MfG
-
In der Initiaite-Funktion kann geändert werden, wohin der lokale Zeiger zeigt, aber eben nur der lokale Zeiger. Um den Wert des wirklich übergebenen Handles/Zeigers zu verändern, bräuchte man eine Referenz oder Kopie darauf.
void Bla::Initiate(HWND windowHandle) { windowHandle = NULL; } void Do() { HWND hwnd = CreateWindow( ... ); Initiaite( hwnd ); // hwnd ist != NULL! }Ich glaube du lässt dich davon verwirren, dass HWND als Zeiger deklariert ist.. Stell dir einfach vor, HWND wäre ein typedef für ein int, ein gültiger Zeiger ist es nämlich sowieso nicht (jedenfalls nicht für dein Programm).
-
Verstehe ich nicht, warum sollte HWND kein gültiger Zeiger sein? Ist doch ein Zeiger auf die Struktur HWND__ ...
void Bla::Initiate(HWND windowHandle) { *windowHandle = xyz... } void Do() { HWND hwnd = CreateWindow( ... ); Initiaite( hwnd ); }Die lokale Variable der Initiate-Funktion zeigt doch auf das hwnd Objekt in Do(), wohin denn sonst? Und per dereferenzierung greife ich auf das Objekt in Do() zu, worauf denn sonst?

MfG
-
Eben das ist es: Dereferenzieren kannst du ein HWND nicht. Die Struktur eines Handles ist nur im Windows-Inneren bekannt, evtl ist ein Handle nur ein Integer, der eine ID für ein entsprechendes Objekt ist.
Dass bei dir ein HWND als HWND__* deklariert ist, erkläre ich mir so: Sind alle Handles typedefs auf ints, dann kannst du problemlosHICON hIco = CreateWindow(...);schreiben, weil es implizit cast-bar ist. Nicht so bei Zeigern auf verschiedene Strukturen, denen ja übrigens ja auch gar kein Inhalt eingebaut wurde.
-
Also ist HWND ein Extrawürstel? Toll Microsoft...
Wie soll man denn richtig mit der API arbeiten können, wenn man nicht mal weis, was hinter den ganzen typedefs steht?Wie soll ich das dumme HWND nun behandeln? Ist das bei allen WINAPI-Typedefs so schwachsinnig?
Also ich versteh das jetzt mit der ID. Daher ist es egal, ob das Handle kopiert wurde, spricht immer noch dasselbe Objekt an...
Also schreib ich jetzt einfach:
HWND Window::getWindowHandle() { return windowHandle; } void Bla::Initiate(HWND windowHandle) { ... }Geht wohl nicht sinnvoller?
MfG
-
Wo ist denn eigentlich genau nun das Problem? Das ist doch gerade mit der Sinn von typedefs, dass du einen Bezeichner auf einen anderen Typ mappen kannst. So kann man später leicht im Hintergrund den abgebildeten Typ ändern.
Was genau HWND nun ist ist auch völlig unerheblich. Es ist einfach eine Art abstrakter Zeiger (Handle eben). Mehr als durch Funktionen reichen macht man damit eh nicht.
-
Ich wollte einfach, dass windowHandle nur durch die Klasse Window veränderbar ist, aber das Handle wird in einer anderen Klasse benötigt, dort wollte ich es nur lesbar machen, geht aber anscheinend ned...
MfG