Fortschrittsanzeige
-
Also bevor ich gesteinigt werde: Hab einiges gelernt in diesem TOpic
Das gibt weder Probleme, noch sonst irgendetwas, denn hinter dem Zeiger verbirgt sich ja schliesslich ein Objekt vom Typ CMyView. Und da ich das ja mal erzeugt habe, wurden auch alle Member-Variablen initialisiert.
Ja das dachte ich auch, das es sich um das CWnd handelt. Das schrieb Rene auch ziemlich am Anfang als ich mit dem Standard anfing. Aber ich verstehe nicht warum es dann nicht mit dynamic_cast klappt ?!
Das würd ich gern noch verstehen.
[ Dieser Beitrag wurde am 30.03.2003 um 23:06 Uhr von Knuddlbaer editiert. ]
-
Jo, Shaggy, kann ich dir nur zustimmen.
Hab mich nicht deutlich ausgedrückt.
Ich meinte es für den Fall, wenn das Control nicht von den MFC erstellt wurde. Dann befindet sich in der Handle-Map kein Eintrag und dann wird ein neues Objekt vom Typ CWnd erstellt, in die Temporary-Map eingetragen und ein Zeiger darauf zurückgeliefert. Und diesen CWnd* wieder in ein CProgressCtrl* oder ähnliches zu casten, kann unter Umständen gefährlich sein.
-
Wenn man der Meinung ist, strikt nach C++-Standard programmieren zu müssen, dann bitte - ist jedem selbst überlassen
Dieser Meinung bin ich ganz und gar nicht. Danke. Aber selbst wenn. Das eine hat mit dem anderen überhaupt nichts zu tun.
aber offensichtlich sind diese beiden Zeilen identisch!?:
Das Wort offensichtlich ist hier schlichtweg falsch. Und wenn du dir die Mühe machst und dich ein wenig mit den C++ Cast auseinandersetzt, dann wirst du auch wissen warum.
Also ich bin mit meinen Feld-Wald-und-Wiesen-Cast
bisher gut über die Runden gekommen, alle Programme laufen problemlos schnell und zuverlässig. Nichts für ungut, aber sollte ich den dynamic_cast benötigen werde ich eine www.c-plusplus.net-Gedenkminute einlegen.
Also dazu fällt mir nur noch Hobbes:
"Why waste time learning when ignorance is instantaneous?"
ein.Es ist sicher jedem selbst überlassen wie er programmiert. Wer sich aber weigert neues zu lernen und dabei auch mal alte Wege zu verlassen, wird meiner Meinung nach irgendwann auf einem Abstellgleis enden.
Wie schon gesagt. Ich will damit nicht sagen, dass du von nun an immer die neuen Casts verwenden sollst. Ich will damit nur sagen, dass du zumindest wissen solltest wozu man sie einsetzt und wo die Vorteile sind.
-
Ich benutze (shame on me
) ebenfalls den C-Cast, da ich zu faul bin, erstens etwas dazuzulernen und zweitens einen Mehraufwand an Tipparbeit einzugehen. Aber ich nenne mich selber einen Hobby-Programmierer. Ich werde nie ein richtiger werden, denn um einer zu werden müsste ich sooo viel lesen. Und dazu bin ich ebenfalls schlichtweg zu faul.
-
Nochmal zur Frage, warum dynamic_cast nicht klappen kann:
Ich weiss nicht genau, wo im Speicher, aber eines ist klar:
Die Laufzeitinformationen, welche bei GetDlgItem zurückgeliefert werden:
CObject::CWndEin dynamic_cast auf CProgressCtrl würde voraussetzen, dass es sich bei den Laufzeitinformationen um
CObject::CWnd::CProgressCtrl handeln muss.Siehe MSDN:
void f() { B* pb = new D; // unclear but ok B* pb2 = new B; D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D ... D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D // cast was bad so pd2 == NULL ... }
-
Wo ist denn dann bitteschön der Unterschied zwischen den beiden Zeilen? Wo ist denn dann der Vorteil von static_cast gegenüber dem ()-cast? Mal abgesehen davon, das ersteres C++ ist?
By the way, ich bin immer bereit Neues zu lernen und mich mit Neuen Dingen auseinanderzusetzen (deswegen schreibe ich hier ja auch immer wieder was). Wenn ich aber keinen wirklichen Nutzen bei Neuen Sachen erkennen kann, dann wende ich die auch selten bis gar nicht an.
Und ich bestimmt nicht der Einzige, der der Meinung ist, dass wenn ich bis an mein Lebensende weder dynamic_cast noch static_cast verwende, definitiv NICHT auf dem Abstellgleis landen werde.Hab mal einen Suchlauf über das VC98-Verzeichnis machen lassen. Kein einziges Mal dynamic_cast gefunden...
Ich sehe schon die Vorteile von dynamic_cast (unter anderem, dass das ursprüngliche Problem damit NICHT gelöst werden kann ... ;-)), jedoch sehe ich noch keinen Nutzen in meinen Anwendungen. Entweder der Pointer ist auch ein Zeiger auf die Klasse, in die ich Casten will, oder er ist NULL. Und mich durch Klassenhierarchien durchwälzen tue ich auch nicht, dazu gibt's virtuelle Funktionen und ähnliches.
@ReneG:
Wenn ich also mit dynamic_cast hier nicht weiterkomme, was macht dann der Ich-arbeite-strikt-nach-C++-Programmierer? Aufgeben? Oder muss er sich mit veralteten Funktionalitäten abfinden?
-
Original erstellt von RenéG:
**Nochmal zur Frage, warum dynamic_cast nicht klappen kann:Ich weiss nicht genau, wo im Speicher, aber eines ist klar:
Die Laufzeitinformationen, welche bei GetDlgItem zurückgeliefert werden:
CObject::CWndEin dynamic_cast auf CProgressCtrl würde voraussetzen, dass es sich bei den Laufzeitinformationen um
CObject::CWnd::CProgressCtrl handeln muss.Siehe MSDN:
[quote]void f() { B* pb = new D; // unclear but ok B* pb2 = new B; D* pd = dynamic_cast<D*>(pb); // ok: pb actually points to a D ... D* pd2 = dynamic_cast<D*>(pb2); // pb2 points to a B not a D // cast was bad so pd2 == NULL ... }
**
[/QUOTE]
Warum funzt das trotzdem?
Mit GetDlgItem von CWnd wird dem gelieferten HWND ein schon existierendes CWnd aus der HandleMap zugeordnet, welches direkt auf das Objekt zeigt, als welches es erstellt wurde. Falls diese Zuordnung nicht existiert, wird ein temporäres CWnd-Objekt erzeugt, welchem das HWND zugeordnet wird.Erst mal vielen Dank für die Antwort. Am Anfang hattest Du aber geschrieben das es sich um das CWnd handelt das on der Klassenhirachie des MFCControls (ok in diesem Speziellen fall das Prograssdings) handelt. Nun zeigst Du quelltext der Zeigt das es sich nicht um das CWnd handelt sondern um eines das temporär erzeugt wird. (Somit geht der dynamic_cast nicht und es ist das der Fall was weiter oben diskutiert wurde). Das mit der Handlemap hab ich nach suchen ebenfalls gefunden und genau das irritiert mich nun stark da es doch irgendwie niht zusammenpasst
Wenn wir das eventuell nich klären könnten... Hätt ich es vllt. komplett verstanden und kann es nachvollziehen. Denn das irritiert mich denn nun doch.
Die Lösung für das ganze sähe z.B. so aus das Control als variable anzulegen (ctrl + doppelklick auf das MFC Control z.B. ProgressBar) und mit DDX_Control
arbeiten. (Kann gerne mal ein kleines Beispiel schreiben das zeigt wie ich es bisher machte....)@ll auf jedenfall schon mal thx das ihr nicht aufgebt es mir zu erklären
[ Dieser Beitrag wurde am 31.03.2003 um 08:59 Uhr von Knuddlbaer editiert. ]
-
@Knuddelbaer
Das mit dem DDX_Control ist uns allen bekannt.Nachteil dieser Methode:
- +1 Zeile für Membervariable in Headerdatei
- +1 Zeile in der DoDataExchange-Methode
- Subclassen des Controls->neue WindowProc, die gar nicht benötigt wird.Und das alles nur, weil ich irgendwo eine Methode habe, die den Fortschrittsbalken per SetPos oder StepIt aktivieren soll?
[ Dieser Beitrag wurde am 31.03.2003 um 09:15 Uhr von RenéG editiert. ]
-
?? Was passt nicht zusammen ??
Wurde das Objekt angelegt und initialisiert, so steht der 'echte' Zeiger in der HandleMap der MFC. Dann funzt auch ein dynamic_cast!
Aber, wenn dieses Objekt existiert, wozu brauche ich dann noch ein GetDlgItem? Dann kann ich ja gleich direkt zugreifen!
2.
Gibt es kein passendes Control, wird ein temporäres CWnd angelegt, welches einfach nur das HWND kapselt und ein paar einfachere Funktionen statt API bereitstellt. Der this-Zeiger kann durchaus benutzt werden. Die aufgerufenen Funktionen des Controls, auf das gecastet wird, dürfen allerdings NUR das HWND das CWnd betreffen.
-
Hm, ich glaub so langsam raff ich es *juhu endlich ?!
*
Also:
Wenn ich das COntrol mit dem DDX Krempel anlege bekomm ich das CWnd aus der Handlemap.
In allen anderen Fällen nur ein temporäres CWnd ?
Die aufgerufenen Funktionen des Controls, auf das gecastet wird, dürfen allerdings NUR das HWND das CWnd betreffen
Hm, wie kann ich das zuverlässig rausbekommen ?
thx
-
Gibt es kein passendes Control, wird ein temporäres CWnd angelegt, welches einfach nur das HWND kapselt und ein paar einfachere Funktionen statt API bereitstellt. Der this-Zeiger kann durchaus benutzt werden. Die aufgerufenen Funktionen des Controls, auf das gecastet wird, dürfen allerdings NUR das HWND das CWnd betreffen.
Und so wie ich das sehe (siehe meine irgendwo weit vorher gezeigten MFC-Source-Auszüge) macht ein CProgressCtrl nix anderes, als Nachrichten an das CWnd (HWND) zu schicken. Also klappt auf jeden Fall ein (CProgressCtrl*)(GetDlgCtrl(ID_MYCTRL)), oder? Aber beim dynamic_cast geht's wieder nicht? Und wie ist es mit static_cast?
Also, ganz ehrlich, bevor ich mich tagelang mit dynamic_cast rumärgere, mache ich meinen FWuW-Cast!
-
Schau in die MFC-Sourcen (siehe z.B. irgendwo weit oben). Und wenn es ein Standard-WinDoof-Control ist, gibt's grundsätzlich keine eigenen Member-Variablen.
-
In allen anderen Fällen nur ein temporäres CWnd ?
Nein, erst wird natürlich geschaut, ob es in der permanenten HandleMap schon das Handle gibt!
Die aufgerufenen Funktionen des Controls, auf das gecastet wird, dürfen allerdings NUR das HWND das CWnd betreffen.
Hm, vielleicht mit 'sizeof(CProgressCtrl)==sizeof(CWnd)'
Also, ganz ehrlich, bevor ich mich tagelang mit dynamic_cast rumärgere, mache ich meinen FWuW-Cast!
Ganz davon abgesehen, dass die Laufzeitinformationen, die ich bei API- und MFC-Programmierung eh nur höchst selten benötige, die Executable unverhältnismässig aufblähen.
[ Dieser Beitrag wurde am 31.03.2003 um 09:46 Uhr von RenéG editiert. ]
-
@ReneG:
Richtig, daran hab ich auch schon gedacht. Was würde ein Sortieralgorithmus für 1.000.000 Elemente mit Verwendung von dynamic_cast wohl länger brauchen?
-
Keine Ahnung, allerdings würde ich für solche Aufgaben eher folgenden Konstrukt verwenden:
B* b; #ifdef _DEBUG b = dynamic_cast<B*>( a); #else b = reinterpret_cast<B*>( a); #endif
oder:
#ifdef _DEBUG #define MYCAST( class, ptr) (dynamic_cast<class*>( ptr)); #else #define MYCAST( class, ptr) (reinterpret_cast<class*>( ptr)); #endif
[ Dieser Beitrag wurde am 31.03.2003 um 09:59 Uhr von RenéG editiert. ]
-
lol
-
Hm,
ich hab mir den Source mal angeschaut, es gibt wirklich ne Handvoll Klassen die keine Member haben.
Ich darf also bei jedem Zugriff dieser Art prüfen ob es legal ist, auch bei jeder neuen Version der MFC (Microsoft is für alles gut
Ich fühle mich dabei dann unsicher vorallem weil ich bei jedem Control was mir über den Weg läuft prüfen darf ob das geht - und das bei jeder neuen Version.
@Shagy so pauschal wie Du es sagst würde ich sagen das die Kosten des einmaligen Casts bei der Sortierung der 1.000.000 Elemente nicht im verhältnis steht.
So eine Frage hab ich noch an Rene,
wann taucht das CWnd denn in der HandleMap nun auf ?!
thx @ll für die geduld - es hat einiges an Wissen mit sich gebracht
-
Also gehe ich recht in der Annahme (hoffentlich diesmal
), dass reinterpret_cast und der ()-cast genau das gleiche machen?
Und static_cast castet nur zwischen Zeigertypen die in einer Klassenhierarchie untereinanderstehen, aber ohne Runtime-Checking, während dynamic_cast das gleiche macht, nur mit Runtime-Checking?
-
Wenn ich eine Sortierfunktion vom Typ
int CMyList::Sort(CBase* p1, CBase* p2)
{
}habe und ich bei jedem Aufruf zweimal dynamic_cast machen muss, dann wird es sicherlich schon einen Unterschied geben. Zumal bei 1.000.000 Elementen diese Funktion wohl etwas häufiger aufgerufen werden wird. Allerdings kann es natürlich sein, dass das checken recht schnell geht. Keine Ahnung, war nur 'ne Idee.
Bei Standard-WinDoof-Controls gibt es - wie gesagt - grundsätzlich keine eigenen Member-Variablen, bei anderen normalerweise schon. Du musst ja nur in die Header-Datei schauen, ob es Member-Variablen gibt oder nicht. Und das geht schnell.
-
Wenn das Steuerelement von den MFC erstellt wurde, dann befindet sich auch ein Eintrag in der Handle-Map mit einem Zeiger auf das wirkliche Objekt. Dann ist ein Cast doch völlig legal. (static_cast<> )