|
Community Links |
Interessengemeinschaften |
Benutzerliste |
Foren durchsuchen |
Stichwortsuche |
Erweiterte Suche |
Uns unterstützen |
Shoppen bei Amazon |
Spende per Patreon |
Spende per PayPal |
Spende per Steady |
alle Möglichkeiten |
Gehe zu... |
![]() |
|
Themen-Optionen
![]() |
Ansicht
![]() |
![]() |
#1 (im Thread / einzeln) |
Che
Gast
Beiträge: n/a
|
Frage @ zeckensack
Ich sehe mir gerade deinen Brotbäcker (geniales Programm, Gratulation!) an und stoße auf folgendes:
ad 2: Was hat das abschließende const in der Deklaration von operator + zu bedeuten? Mfg |
![]() ![]() |
![]() |
#2 (im Thread / einzeln) |
Gold Member
|
Er macht das wohl so, damit Speicher gespart wird, besonders was das Kopieren von Objekten angeht. Eine Referenz wird ja intern vom Compiler als Pointer gehandhabt und ist deshalb auch 32-Bit lang.
Übergibst du eine konstante Referenz so sind das in jedem Fall nur 32-Bit an Daten, die kopiert werden müssen. Sonst (also Call-By-Value) müsste ja das gesamte ExtremeFloat Objekt vom Copy-Konstruktor kopiert werden und das ist mit absoluter Sicherheit größer als 32-Bit, die der interne Pointer fressen würde. Und das const zusammen mit der Referenz halt aus dem Grunde, dass man die Referenz ja nicht ändern soll. Wenn ich was zu einem ExtremeFloat dazuzählen, dann will ich den Teil den ich effektiv dazupacke ja nicht ändern. Zu 2) Das const dahinter der Deklaration gibt an, dass in dieser Klassenmethode keine Daten verändert werden sollen bzw. verspricht dem Compiler dieses. Das ist einmal gut zur Fehlersuche, wenn man wieder mal nicht == sondern nur = getippt hat und dann natürlich für den Compiler zur Optimierung. In const Methoden kann man dann auch nur const-Methoden der Klassenmember aufrufen, das nur so am Rande. Alles richtig so zecki? cya liquid
-=Assume your processor is infinitely fast. It's memory access that kills you.=-
Uni-Bielefeld.de (und es gibt sie doch!) Geändert von liquid (2003-03-24 um 20:29:42 Uhr) |
![]() |
![]() ![]() |
![]() |
#4 (im Thread / einzeln) |
Grandmaster Member
Registriert: 2002-03-10
Beiträge: 12.026
|
Alles richtig @ liquid
![]() Noch ergänzend, const class& ist für C++ die bevorzugte Deklaration für solche Operatoren. Dadurch wird erstens solcher Code möglich
Noch ad 2) dieser Operator ist als Klassenmember deklariert. Es gibt also zwei Operanden, einmal *this (implizit, da Klassenmember), einmal rhs (right hand side) aus der Parameterliste. Der Copy-Konstruktor 'will' übrigens die gleiche Deklaration sehen, insofern habe ich mich lediglich an allgemeinen Konventionen von C++ orientiert. Weiter ad 2) Die beiden Operanden dürfen von einer sauberen Addition nicht verändert werden, ergo will ich beide const deklarieren. Ich gebe ein neues ExtremeFloat zurück, dies ist das einzige auf das ich sinnvollerweise schreibend zugreifen muß. Das const hinter der Parameterliste modifiziert nun den this-Pointer. Anstatt 'ExtremeFloat* this' muß man ihn sich nun als 'const ExtremeFloat* this' deklariert vorstellen - im Scope der Implementation des Operators. |
![]() |
![]() ![]() |
![]() |
#5 (im Thread / einzeln) |
Che
Gast
Beiträge: n/a
|
Ahhh ja, tolle Sache dieses C++ Teufelszeug...
![]() Und dann hab ich noch was gefunden ![]()
Wenn ich alles richtig verstehe deklarierst du da einen ExtremeFloat und übergibst dem Konstruktor einen dereferenzierten Pointer auf einen ExtremeFloat = einen ExtremeFloat. Einmal abgesehen davon dass ich nirgends einen entsprechenden Konstruktor gefunden habe (da hab ich dann wohl was übersehen ![]() btw. was ist der Copy Konstruktor? MfG |
![]() ![]() |
![]() |
#6 (im Thread / einzeln) |
Gold Member
|
Also ich mutmaße mal wieder ein wenig (wenn ich darf *g*).
Dieser Aufruf findet mit Sicherheit in einer Klassenmethode der ExtremeFloat class statt. Dort wird er benutzt (soweit ich das sehen kann), um von sich selbst eine Kopie anzufertigen. Also die Klasse auf die die Klassenmethode aufgerufen wird, legt von sich selbst eine Kopie an. Der entsprechende Konstruktur müsste folgendermaßen deklariert worden sein (ich habe den Brot Code zwar auch in meinem Code-Archiv, hab mich aber noch net näher mit außeinandergesetzt). ExtremeFloat(const ExtremeFloat& rhs); Das ist wieder der besagte Copy-Constructor, der Objekte als Kopien eines anderen gleichartigen Objekts anlegt. Hier nimmt er einfach den dereferenzierten this-Zeiger der Klassenmethode auf und erzeugt eine Kopie der Daten auf dieser this-Zeiger zeigt. Denn den this-Zeiger alleine kann man dem Copy-Constructor nicht übergeben, es muss schon die derefenzierte Version sein. Diese wird anderesseits auch weider als Pseudo-Zeiger übergeben (da ja Call-By-Reference). Hoffe das stimmt alles so. cya liquid EDIT: Copy-Constructor: Ist eigentlich ein handelsüblicher Konstruktor, dem als Parameter ein Objekt, der Sorte was er erzeugen soll (also wenn er sein abc-Objekt erzeugen soll, dann muss ihm auch ein abc-Objekt übergeben werden), übergeben wird. Der Kopiekonstruktor ist immer dann in Aktion, wenn man Call-By-Value durchführt, da dort ja das übergebene Objekt kopiert werden muss. Und da ist es halt sicherer, wenn man eine "tiefe" Kopie abliefern, als eine lasche "flache", die dann Pointerfehler aufwirft.
-=Assume your processor is infinitely fast. It's memory access that kills you.=-
Uni-Bielefeld.de (und es gibt sie doch!) Geändert von liquid (2003-03-25 um 19:07:47 Uhr) |
![]() |
![]() ![]() |
![]() |
#7 (im Thread / einzeln) |
3D-Guru
Registriert: 2001-08-08
Beiträge: 10.068
|
Originally posted by Che Der Copy Constructor macht standardmäßig "Memberwise Initialisation", d.h. für jeden Member wird einzeln der Copy Constructor aufgerufen, natürlich mit dem entsprechenden Member aus der zu kopierenden Klasse als Argument. Geändert von Xmas (2003-03-25 um 22:29:44 Uhr) |
![]() |
![]() ![]() |
![]() |
#8 (im Thread / einzeln) |
Grandmaster Member
Registriert: 2002-03-10
Beiträge: 12.026
|
Noch 'ne Ergänzung zum Copy-Constructor:
Wenn man das so gemacht hat, kann man ein Objekt direkt als Identität eines anderen erzeugen, und somit den 'normalen' Konstruktor umgehen. Das lohnt sich, wenn dieser nicht-trivial ist. In meinem Fall setzt zB der Default-Constructor das 'ExtremeFloat' auf Null, indem alle 32 Bytes geschrieben werden. Ist zwar nur ein sehr kleiner Overhead, aber immerhin. Wenn diese Operation wie in meinem Fall sehr oft passiert, dann möchte man dies vermeiden können. ________________ Eigentlich sollte ein Compiler bei folgender Zeile
MSVC6 SP5 ist dafür allerdings offensichtlich zu blöde, selbst im Release-Build mit voller Optimierung (ich hab's ausgemessen). Es wird zuerst der 'normale' Konstruktor aufgerufen, und danach der assignment operator - der hier: ExtremeFloat& operator =(const ExtremeFloat& rhs); Deswegen dieses komische Dings da oben, um den Aufruf des copy constructors zu erzwingen. Ich kann wirklich nur jedem empfehlen, MinGW/GCC3.2 für Release-Builds zu benutzen, da ist MSVC ein Scheiß dagegen. Der Debugger ist ganz nett, aber der Compiler ... ![]() |
![]() |
![]() ![]() |
![]() |
#10 (im Thread / einzeln) |
Che
Gast
Beiträge: n/a
|
Wo wir hier gerade dabei sind die Semantik von C++ auseinanderzunehmen:
Was sind eigentlich Singletons und wozu sind sie da? Ich hab auf einem anderen Board gelesen (dabei gings um Engine-Design) das man sich damit "die häßlichen extern-Konstrukte" sparen kann, und das interessiert mich natürlich schon... ![]() MfG |
![]() ![]() |
![]() |
#11 (im Thread / einzeln) |
3DCenter Crew & 3D-Guru
|
Als Singletons bezeichnet man Klassen von denen es in einem Process immer nur genau eine Instanz gibt und man auch keine zusätzlichen erzeugen kann.
Um das ganze zu erreichen gibt es ein paar Wege. Was aber alle gemeinsam haben ist das es keinen öffentlichen Konstruktor gibt. |
![]() |
![]() ![]() |
![]() |
#12 (im Thread / einzeln) |
Grandmaster Member
Registriert: 2002-03-10
Beiträge: 12.026
|
Originally posted by Che ![]() Ich nutze 'extern-Konstrukte' eigentlich nur für Singletons (und globale Variablen; Ziel der Übung ist aber globale Variablen durch Singletons zu ersetzen, von daher auch wurscht).
![]() |
![]() |
![]() ![]() |
![]() |
#14 (im Thread / einzeln) |
Grandmaster Member
Registriert: 2002-03-10
Beiträge: 12.026
|
Originally posted by Demirug ![]() Ich hätte auch noch diverse 'Factory'-Klassen im Angebot, die sind aber 'geringfügig' länger ![]() Der Hauptgrund das so zu machen, ist daß der Konstruktor sofort aufgerufen wird wenn der Prozess startet. Dann muß ich das nicht selber machen ![]() Und nun sag, was stört dich daran? ![]() |
![]() |
![]() ![]() |
![]() |
#15 (im Thread / einzeln) |
3DCenter Crew & 3D-Guru
|
Originally posted by zeckensack Der Hauptgrund das so zu machen, ist daß der Konstruktor sofort aufgerufen wird wenn der Prozess startet. Dann muß ich das nicht selber machen Und nun sag, was stört dich daran? |
![]() |
![]() ![]() |
![]() |
#18 (im Thread / einzeln) |
Che
Gast
Beiträge: n/a
|
Originally posted by Demirug /me glaubt: 3DC -> bestes Forum im deutsprschigen Raum (mal wieder ![]() Link hab ich erst kurz überflogen aber ich bin sicher er hilft mir weiter... ![]() |
![]() ![]() |
![]() |
#19 (im Thread / einzeln) |
Grandmaster Member
Registriert: 2002-03-10
Beiträge: 12.026
|
Originally posted by Demirug ![]() Weder Mäuse noch Bildschirme sind IMO sinnvolle Kandidaten für Singletons. (btw, wenn das Smalltalk ist, dann bin ich froh das nicht gelernt zu haben ...) Die simpelste Lösung für deine Forderung ist wohl, einfach alle Members static zu machen. Damit hätte ich eigentlich kein Problem. Ich hab's auch schon gemacht, aber auch wieder nur weil MSVC6 so scheiße optimiert. Dann könnte man zwar beliebig viele Instanzen erzeugen, diese wären aber im Grunde nur Referenzen auf 'das' Objekt. Diesen ganzen Overhead mit current etc würde ich mir nicht mal in die Haare schmieren ![]() |
![]() |
![]() ![]() |
![]() |
#20 (im Thread / einzeln) |
3DCenter Crew & 3D-Guru
|
Originally posted by zeckensack |
![]() |
![]() ![]() |
![]() |
Lesezeichen |
Ansicht |
![]() |
![]() |
![]() |
|
|