Komponentenmanipulation über Index
-
Braunstein schrieb:
Der ComponentIndex wird automatisch festgelegt wenn die Komponente dem Formular zugefügt wird. Den solltest du nicht manipulieren.
ich schrieb:
Solange es übersichtlich bleibt kann ich das doch theoretisch machen. Warum sollte ich nicht?
akari schrieb:
Weil diese Eigenschaft nicht dazu gedacht ist. Es ist nicht klar was deine Zuweisungen für Auswirkungen hat
BCB-Hilfe schrieb:
ComponentIndex wird intern für iterative Zuweisungsprozeduren verwendet.
Versteht mich bitte nicht falsch in meiner Unwissenheit - also: Wenn ComponentIndex nicht manipuliert werden darf, wäre er doch für uns Nutzer nicht manipulierbar (read only)!? Bei anderen Eigenschaften ist es doch auch so... Im Zitat aus der Hilfe steht nicht, dass ComponentIndex nicht manipuliert werden sollte.
Wenn ich selbst Indizes zuweise, was soll passieren, außer dass ich sie kenne? Ich stelle mir das so vor: BCB schaut nach den Komponenten und bereits vergebenen Indizies (ich habe sie gleich im Aufruf der Main-Form manipuliert) und vergibt dann an die verbleibenden Komponenten ohne Index freie Indizes. Was soll da schief gehen?
Tja, und was "iterative Zuweisungsprozeduren" sind, müsste ich mich erstmal schlau machen...
akari schrieb:
Solche Sammlungen von Komponenten sollten gleich in einem eigenen, passenden, eventuell dynamischen Array verwaltet werden. Dann muß man weder unnütz iterieren, noch unnütz casten.
Dieses Vorgehen wird in den genannten FAQ-Einträgen ja auch erklärt.Okay, bin gewissermaßen schon wieder zu den FAQ unterwegs.
-
Kolumbus schrieb:
Wenn ich selbst Indizes zuweise, was soll passieren, außer dass ich sie kenne? Ich stelle mir das so vor: BCB schaut nach den Komponenten und bereits vergebenen Indizies (ich habe sie gleich im Aufruf der Main-Form manipuliert) und vergibt dann an die verbleibenden Komponenten ohne Index freie Indizes. Was soll da schief gehen?
Die Inidizes müsse ja fortlaufend sein (sonst kann man ja nicht darüber iterieren). Wenn du also einen bereits vergebenen Index zuweisen willst, ändert sich die ganze Anordnung. Du weißt aber nicht wie. D.h. nach mehreren Zuweisungen kann der erste von dir vergebene Index intern schon wieder geändert sein. Das kann also schief gehen.

-
Hallo
Versteht mich bitte nicht falsch in meiner Unwissenheit - also: Wenn ComponentIndex nicht manipuliert werden darf, wäre er doch für uns Nutzer nicht manipulierbar (read only)!? Bei anderen Eigenschaften ist es doch auch so... Im Zitat aus der Hilfe steht nicht, dass ComponentIndex nicht manipuliert werden sollte.
Das stimmt grundsätzlich.
Wenn ich selbst Indizes zuweise, was soll passieren, außer dass ich sie kenne? Ich stelle mir das so vor: BCB schaut nach den Komponenten und bereits vergebenen Indizies (ich habe sie gleich im Aufruf der Main-Form manipuliert) und vergibt dann an die verbleibenden Komponenten ohne Index freie Indizes. Was soll da schief gehen?
Leider ist nicht klar ob es wirklich so ist. Es könnte genauso gut sein das du durch das Setzen des ComponentIndex intern die Verwaltungsstruktur durcheinander bringst, mit Auswirkungen die vielleicht erst unter gewissen Umständen sich bemerkbar machen.
/Edit : Und natürlich Braunsteins Einwand : Mit dem setzen von ComponentIndex kannst du maximal eine Reihe festmachen. Wenn du aber zwei oder mehr verschiedene Sammlungen von Arrays willst, wirst du dir dann selber die Indexe verschieben.Tja, und was "iterative Zuweisungsprozeduren" sind, müsste ich mich erstmal schlau machen...
Ein Schleife die für alle Komponenten eine bestimmte Methode aufruft.
bis bald
akari
-
So, das Zuweisen von Indizes habe ich jetzt rausgenommen - ihr habt mich überzeugt, dass die Folgen in ihrer Gesamtheit schlecht überschaubar sind (erst recht für mich als Anfänger).
ich schrieb:
Tja, und was "iterative Zuweisungsprozeduren" sind, müsste ich mich erstmal schlau machen...
akari schrieb:
Eine Schleife die für alle Komponenten eine bestimmte Methode aufruft.
Danke. Super, sowas mache ich ja schon... Ich habe mir somit die Hände gewaschen und hinterher gelernt, dass es "Hygene" heißt

Hier jetzt mal meine, inzwischen fertiggestellte, Ereignisbehandlungsmethode /~routine:
void __fastcall TForm4::CheckBoxClick(TObject *Sender) { unsigned short j= dynamic_cast<TCheckBox*>(Sender)->Tag; unsigned short k; for(k=0; k < (Form4->ComponentCount-1); ) { if((this->Components[k]->ClassNameIs("TEdit")) && (dynamic_cast<TEdit*>(this->Components[k])->Tag==j)) { TEdit *VirtualEdit= dynamic_cast<TEdit*>(this->Components[k]); if(!VirtualEdit->Enabled) VirtualEdit->Enabled= true; else { VirtualEdit->Enabled= false; VirtualEdit->Text= "0"; } k= Form4->ComponentCount - 1; // Schleifenabbruch herbeiführen } else k++; } }Ist doch im Prinzip auch eine iterative Zuweisungsoperation?
Dazu noch eine Frage: Ist diese Version besser oder schlechter als die Obige?:
void __fastcall TForm4::CheckBoxClick(TObject *Sender) { unsigned short j= dynamic_cast<TCheckBox*>(Sender)->Tag; unsigned short k; for(k=0; k < (Form4->ComponentCount-1); ) { if((this->Components[k]->ClassNameIs("TEdit")) && (dynamic_cast<TEdit*>(this->Components[k])->Tag==j)) { if(!dynamic_cast<TEdit*>(this->Components[k])->Enabled) dynamic_cast<TEdit*>(this->Components[k])->Enabled= true; else { dynamic_cast<TEdit*>(this->Components[k])->Enabled= false; dynamic_cast<TEdit*>(this->Components[k])->Text= "0"; } k= Form4->ComponentCount - 1; // Schleifenabbruch herbeiführen } else k++; } }Und wenn, warum ist die Eine besser als die Andere?
-
Hallo
dynamic_cast ist immer eine Laufzeit-Überprüfung. Damit sollte man es so wenig wie möglich aufrufen. Und wenn du dynamic_cast einsetzt, brauchst du auch kein ClassName mehr Also ungefähr so
void __fastcall TForm4::CheckBoxClick(TObject *Sender) { unsigned short j= dynamic_cast<TCheckBox*>(Sender)->Tag; unsigned short k; for(k=0; k < (Form4->ComponentCount-1); k++) { TEdit *VirtualEdit= dynamic_cast<TEdit*>(this->Components[k]); if (VirtualEdit) { if(!VirtualEdit->Enabled) VirtualEdit->Enabled= true; else { VirtualEdit->Enabled= false; VirtualEdit->Text= "0"; } break; // Schleifenabbruch herbeiführen } } }Allerdings wäre es noch besser wenn du die Variante aus der FAQ nimmst die mit einem eigenen DynamicArray arbeitet.
bis bald
akari
-
akari schrieb:
...wenn du dynamic_cast einsetzt, brauchst du auch kein ClassName mehr...
Ahh, verstehe... Und zwar wegen:
BCB-Hilfe schrieb:
... Wenn die Umwandlung durchgeführt werden kann, so wandelt der Ausdruck dynamic_cast< T > (ptr) den Zeiger ptr in den gewünschten Typ um. Falls die Umwandlung eines Zeigertyps nicht möglich ist, hat der zurückgegebene Zeiger den Wert NULL. ...
stimmts?
Und die Sache mit dem Schleifenabbruch ist mir ja peinlich... War schon wieder zu einfach für mich!

Zur FAQ-Variante: wenn sich herausstellt dass ich noch Zeit habe, werde ich das machen!
Wikipedia schrieb:
... Ein wichtiger Faktor bei der Entwicklung eines Systems ist aus Wettbewerbsgründen die Zeit. So muss sich der Ingenieur in der Praxis häufig mit einer nichtidealen Lösung zufrieden geben, die aber dennoch als gut einstufbar ist. ...

-
Mir ist da gerade noch etwas aufgefallen: Ist meine Lösung in diesem Fall nicht besser, weil dynamic_cast nur ausgeführt wird, wenn die Komponente ein TEdit ist? Mit der Lösung die akari angeboten hat, wird doch bei jeder Komponente ein dynamic_cast versucht... macht in meinem speziellen Fall einen maximalen Unterschied von 31 dynamic_casts (derzeit 48 Komponenten auf dem Formular, 17 davon TEdit). Hab ich was übersehen?

-
Hallo
Ahh, verstehe... Und zwar wegen:
stimmts?Korrekt.
Mir ist da gerade noch etwas aufgefallen: Ist meine Lösung in diesem Fall nicht besser, weil dynamic_cast nur ausgeführt wird, wenn die Komponente ein TEdit ist? Mit der Lösung die akari angeboten hat, wird doch bei jeder Komponente ein dynamic_cast versucht... macht in meinem speziellen Fall einen maximalen Unterschied von 31 dynamic_casts (derzeit 48 Komponenten auf dem Formular, 17 davon TEdit). Hab ich was übersehen?
Du übersiehst zwei Sachen :
- Auch die Ermittlung des ClassName sowie der AnsiString-Vergleich mit "TEdit" braucht seine Verarbeitung.
- Wenn du schon auf ClassName vergleichst, brauchst du auch kein dynamic_cast sondern dann reicht ein static_cast ohne Überprüfung.bis bald
akari
-
Wenn mans genau nimmt sollte auch bei der CheckBox-Umwandlung ein Test rein.
AlsoTCheckBox* check(dynamic_cast<TCheckBox*>(Sender)); if( !check) return; unsigned short j= check->Tag;
-
akari schrieb:
Du übersiehst zwei Sachen :
- Auch die Ermittlung des ClassName sowie der AnsiString-Vergleich mit "TEdit" braucht seine Verarbeitung.Ok, und was ist aufwendiger? Das oder dynamic_cast?
akari schrieb:
- Wenn du schon auf ClassName vergleichst, brauchst du auch kein dynamic_cast sondern dann reicht ein static_cast ohne Überprüfung.
Kannst du das bitte nochmal anders (und evtl ausführlicher) formulieren? Ich steh' schon wieder auf der Leitung!

Braunstein schrieb:
Wenn mans genau nimmt sollte auch bei der CheckBox-Umwandlung ein Test rein.
Aber die Ereignisbehandlung ist doch für CheckBoxClick; Sender ist doch immer ein TCheckBox-Element
Wozu der Test 
-
Hallo
Ok, und was ist aufwendiger? Das oder dynamic_cast?
Gute Frage. Schwer zu sagen. Ich vermute die ClassName-Variante.
Kannst du das bitte nochmal anders (und evtl ausführlicher) formulieren? Ich steh' schon wieder auf der Leitung!
Du machst momentan erst die ClassName-Überprüfung und dann die dynamic_cast-Umwandlung mitsamt Überprüfung. Damit ist eine Überprüfung doppelt. Und darum reicht eigentlich ein dynamic_cast aus.
Du kannst natürlich auch die ClassName-Überprüfung machen und statt dem dynamic_cast einfach static_cast verwenden. Denn static_cast ist nur eine Umwandlung ohne Überprüfung, die man nehmen darf wenn man sich wirklich sicher ist. Dafür ist static_cast zur Laufzeit kostenlos.Aber die Ereignisbehandlung ist doch für CheckBoxClick; Sender ist doch immer ein TCheckBox-Element
Braunstein meint genau das was ich oben gesagt habe : dynamic_cast brauchst du nur wenn du dir nicht sicher bist und ein Überprüfung braucht, ob die Umwandlung wirklich machbar ist. Das bedeutet aber auch das nach jedem sinnvollen dynamic_cast auch das Ergebnis von dynamic_cast überprüft werden sollte.
Wenn du dir zur Entwurfszeit sicher bist das es funktioniert dann reicht ein static_cast.
bis bald
akari
-
Kolumbus schrieb:
[Aber die Ereignisbehandlung ist doch für CheckBoxClick;
Die ist nur dafür gedacht. Ja. Wenn du sie aber mal versehentlich einem TEditClick zuweist knallt es. Dazu brauchst du nur mal im Objektinspektor falsch auswählen.
-
Hallo
Braunstein schrieb:
Kolumbus schrieb:
[Aber die Ereignisbehandlung ist doch für CheckBoxClick;
Die ist nur dafür gedacht. Ja. Wenn du sie aber mal versehentlich einem TEditClick zuweist knallt es. Dazu brauchst du nur mal im Objektinspektor falsch auswählen.
Also nur wegen dieser Befürchtung würde ich kein dynamic_cast verwenden. Soviel Kontrolle hab ich schon über mein Projekt

bis bald
akari
-
Mag sein. Ich finde es nur eine nützliche Angewohnheit, bei dynamic_cast grundsätzlich zu prüfen. Kann sein das das manchmal unnötig ist, aber auf keinen Fall fehlerhaft.

Wie du ja schon gesagt hast kann man ja sonst gleich static_cast nehmen.
-
Hallo
Braunstein schrieb:
Mag sein. Ich finde es nur eine nützliche Angewohnheit, bei dynamic_cast grundsätzlich zu prüfen. Kann sein das das manchmal unnötig ist, aber auf keinen Fall fehlerhaft.

Genau

Wie du ja schon gesagt hast kann man ja sonst gleich static_cast nehmen.
Und genau das würde ich in diesem Fall auch machen.
bis bald
akari
-
So, jetzt würde ich gern einen ausgeben; Ihr seid spitze - ich glaub' ich hab's gerafft!

Nach Abwägung eurer Argumente sieht das (vorläufige) Ergebnis nun so aus:void __fastcall TForm4::CheckBoxClick(TObject *Sender) { unsigned short j= static_cast<TCheckBox*>(Sender)->Tag; for(unsigned short k= 0; k < (this->ComponentCount-1); k++) { if((this->Components[k]->ClassNameIs("TEdit")) && (static_cast<TEdit*>(this->Components[k])->Tag==j)) { TEdit *VirtualEdit= static_cast<TEdit*>(this->Components[k]); if(!VirtualEdit->Enabled) VirtualEdit->Enabled= true; else { VirtualEdit->Enabled= false; VirtualEdit->Text= "0"; } break; } } } //---------------------------------------------------------------------------
-
Eine kleine Änderung
for(unsigned short k= 0; k < (ComponentCount-1); k++) { TEdit* VirtualEdit = dynamic_cast<TEdit*>(Components[k]); if(VirtualEdit && VirtualEdit->Tag==j) { if(!VirtualEdit->Enabled) VirtualEdit->Enabled= true; else { VirtualEdit->Enabled= false; VirtualEdit->Text= "0"; } break; } }
-
Ok, das this spare ich mir gerne. Ich weiß ja zur Entwicklungszeit wo ich mich bewege.

Das deine Version übersichtlicher ist gebe ich zu und sie entspricht ja auch deinen dargelegten Prinzipien, aber ist sie zur Laufzeit ressourcensparender? Du castest jede Komponente, ich überprüfe bei jeder den Namen... wie bekommen wir raus, was günstiger ist? Gibts da eine Möglichkeit?
-
dynamic_cast wie auch ClassNameIs sollten ähnliche Laufzeiten haben, so dass sich beide Versionen nicht viel nehmen. Sie müssen ja beide intern überprüfen welche Klasse wirklich hinter dem Object-Zeiger steckt. Wenn du es genau wissen willst mußt du es halt mal überprüfen.
-
Jetzt habe ich das mal getestet.
Die dynamic_cast Variante ist deutlich schneller als ClassNameIs (mehr als Faktor 20).