Zurück   3DCenter Forum > Software-Hilfe Foren > Programmierung
Registrieren Hilfe Community Kalender Heutige Beiträge Suchen Uns unterstützen

Antwort
 
Themen-Optionen Ansicht
Alt 2003-03-24, 20:16:02   #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:
Code:
void operator += (const ExtremeFloat& rhs);
ExtremeFloat operator + (const ExtremeFloat& rhs) const;
ad 1: Warum in aller Welt const UND Referenz? const verwende ich doch um einen Parameter aus Versehen NICHT zu ändern, und eine Referenz verwende ich UM einen Parameter zu ändern. (geht ja normal mit call-by-value nicht) Beides zusammen erscheint mir ziemlich kontraproduktiv...

ad 2: Was hat das abschließende const in der Deklaration von operator + zu bedeuten?

Mfg
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-24, 20:28:51   #2 (im Thread / einzeln)
liquid
Gold Member
 
Benutzerbild von liquid
 
Registriert: 2002-11-24
Beiträge: 556
liquid eine Nachricht über ICQ schicken
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)
liquid ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-24, 22:45:08   #3 (im Thread / einzeln)
micki
Admiral Member
 
Registriert: 2002-08-14
Beiträge: 2.744
1+ @ liquit



MfG
micki
micki ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-25, 03:31:17   #4 (im Thread / einzeln)
zeckensack
Grandmaster Member
 
Benutzerbild von zeckensack
 
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
Code:
ExtremeFloat a,b,c;
c=a+b;     //look mom, no pointers!
, zweitens eben der eingebaute 'sanity check' const, der logische Fehler im Code zu vermeiden hilft.

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.

zeckensack ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-25, 18:42:01   #5 (im Thread / einzeln)
Che
Gast
 
Beiträge: n/a
Ahhh ja, tolle Sache dieses C++ Teufelszeug...

Und dann hab ich noch was gefunden
Code:
ExtremeFloat tmp(*this);
Anm.: aus einer Methode von ExtremeFloat

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 ) frage ich mich ob das überhaupt erlaubt ist. Man kann doch einem Konstruktor nicht als Parameter ebenjenes Objekt übergeben, das er konstruieren soll...oder doch ?

btw. was ist der Copy Konstruktor?

MfG
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-25, 19:03:06   #6 (im Thread / einzeln)
liquid
Gold Member
 
Benutzerbild von liquid
 
Registriert: 2002-11-24
Beiträge: 556
liquid eine Nachricht über ICQ schicken
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)
liquid ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-25, 22:08:44   #7 (im Thread / einzeln)
Xmas
3D-Guru
 
Benutzerbild von Xmas
 
Registriert: 2001-08-08
Beiträge: 10.068
Zitat:
Originally posted by Che
Ahhh ja, tolle Sache dieses C++ Teufelszeug...

Und dann hab ich noch was gefunden
Code:
ExtremeFloat tmp(*this);
Anm.: aus einer Methode von ExtremeFloat

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 ) frage ich mich ob das überhaupt erlaubt ist. Man kann doch einem Konstruktor nicht als Parameter ebenjenes Objekt übergeben, das er konstruieren soll...oder doch ?

btw. was ist der Copy Konstruktor?
Genau das ist der Copy Constructor. Ein solcher wird übrigens automatisch erzeugt, falls keiner explizit deklariert wird, genauso wie der Default Constructor und Assignment Operator (operator= ). Deswegen findest du diese auch im Code nicht.

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)
Xmas ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-26, 15:22:42   #8 (im Thread / einzeln)
zeckensack
Grandmaster Member
 
Benutzerbild von zeckensack
 
Registriert: 2002-03-10
Beiträge: 12.026
Noch 'ne Ergänzung zum Copy-Constructor:
Code:
class
ExtremeFloat
{
   ExtremeFloat(const ExtremeFloat& rhs);
};
Das ist der copy constructor. Oder anders gesagt: wenn man einen solchen haben will, dann muß er nach Standard-C++ exakt so aussehen.
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
Code:
ExtremeFloat tmp=*this;
bereits von sich aus darauf kommen, daß der Copy Constructor gefragt ist. Schließlich erzeuge ich in dieser Zeile ein neues Objekt und weise sofort ein anderes zu. Ein 'Eigenleben' braucht tmp einfach nicht.

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 ...

zeckensack ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-03-26, 17:33:10   #9 (im Thread / einzeln)
Che
Gast
 
Beiträge: n/a
Aaaah, also wieder mal alles wegen der ewigen Geißel Geschwindigkeit...

Vielen Dank ihr drei
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 18:42:53   #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
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 18:52:40   #11 (im Thread / einzeln)
Demirug
3DCenter Crew & 3D-Guru
 
Benutzerbild von Demirug
 
Registriert: 2002-05-14
Beiträge: 22.430
Demirug eine Nachricht über MSN schicken
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.

Demirug ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 19:04:27   #12 (im Thread / einzeln)
zeckensack
Grandmaster Member
 
Benutzerbild von zeckensack
 
Registriert: 2002-03-10
Beiträge: 12.026
Zitat:
Originally posted by Che
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
Hmmm
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).

Code:
//Cpu.h
#define CPU_CAPS_RDTSC 1
#define CPU_CAPS_MMX 2
#define CPU_CAPS_SCREAMING_SINDIE 4
#define CPU_CAPS_STREAMING_STORES 8
#define CPU_CAPS_3DNOW 16
#define CPU_CAPS_3DNOW_ENHANCED 32
#define CPU_CAPS_SSE2 64

class
Cpu
{
public:
	Cpu();
	uint caps;
};

//this is a conceptually a singleton, so we'll declare the instance right away
//defined in cpu.cpp
extern Cpu cpu;
Code:
//Cpu.cpp
#include "common.h"
#include "x86_feature_detect.ah"
#include "cpu.h"
#include <stdio.h>

Cpu cpu;

Cpu::Cpu()
{
	caps=x86_detect_cpu_features();

	printf("x86");
	if (caps&CPU_CAPS_RDTSC) printf("/RDTSC");
	if (caps&CPU_CAPS_MMX) printf("/MMX");
	if (caps&CPU_CAPS_3DNOW)
	{
		printf("/3DNow!");
		if (caps&CPU_CAPS_3DNOW_ENHANCED) printf("+");
	}
	if (caps&CPU_CAPS_SCREAMING_SINDIE) printf("/SSE");
	if (caps&CPU_CAPS_SSE2) printf("/SSE2");
	printf("\n");
}
Obacht: dies ist Code unter LGPL

zeckensack ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 19:15:38   #13 (im Thread / einzeln)
Demirug
3DCenter Crew & 3D-Guru
 
Benutzerbild von Demirug
 
Registriert: 2002-05-14
Beiträge: 22.430
Demirug eine Nachricht über MSN schicken
Zecki das ist aber kein gutes Singleton

Demirug ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 19:19:52   #14 (im Thread / einzeln)
zeckensack
Grandmaster Member
 
Benutzerbild von zeckensack
 
Registriert: 2002-03-10
Beiträge: 12.026
Zitat:
Originally posted by Demirug
Zecki das ist aber kein gutes Singleton
Das ist ein sehr einfaches Singleton

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?

zeckensack ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 19:30:54   #15 (im Thread / einzeln)
Demirug
3DCenter Crew & 3D-Guru
 
Benutzerbild von Demirug
 
Registriert: 2002-05-14
Beiträge: 22.430
Demirug eine Nachricht über MSN schicken
Zitat:
Originally posted by zeckensack
Das ist ein sehr einfaches Singleton

Ich hätte auch noch diverse 'Factory'-Klassen im Angebot, die sind aber 'geringfügig' länger
hehe Factorys habe ich hier auch ein paar. Hüllenklassen (braucht man bei C++ nicht)kann ich auch anbieten.

Zitat:
Der Hauptgrund das so zu machen, ist daß der Konstruktor sofort aufgerufen wird wenn der Prozess startet. Dann muß ich das nicht selber machen
Ja das ist schon klar. Das ist aber keine Forderung bei Singletons

Zitat:
Und nun sag, was stört dich daran?
Das ich immer noch so viele Instanzen von der Klasse erzeugen kann wie ich will bei einem Singleton darf das nicht möglich sein.

Demirug ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 19:45:06   #16 (im Thread / einzeln)
Che
Gast
 
Beiträge: n/a
Äääh, ich versteh das ganze jetzt überhaupt nicht ?-)
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 20:10:23   #17 (im Thread / einzeln)
Demirug
3DCenter Crew & 3D-Guru
 
Benutzerbild von Demirug
 
Registriert: 2002-05-14
Beiträge: 22.430
Demirug eine Nachricht über MSN schicken
Che -> http://www.object-arts.com/Education.../Singleton.htm

Demirug ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 20:18:13   #18 (im Thread / einzeln)
Che
Gast
 
Beiträge: n/a
Zitat:
Originally posted by Demirug
Che -> http://www.object-arts.com/Education.../Singleton.htm
Ich kann nicht aufhören mich über euch zu wundern. Ihr habt wohl wirklich zu jedem noch so ausgefallenen Thema Hilfe bereit!

/me glaubt: 3DC -> bestes Forum im deutsprschigen Raum (mal wieder)

Link hab ich erst kurz überflogen aber ich bin sicher er hilft mir weiter...
  Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 20:34:40   #19 (im Thread / einzeln)
zeckensack
Grandmaster Member
 
Benutzerbild von zeckensack
 
Registriert: 2002-03-10
Beiträge: 12.026
Zitat:
Originally posted by Demirug
Che -> http://www.object-arts.com/Education.../Singleton.htm
Die schießen aber wirklich mit Thrombosen auf Spatzen
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

zeckensack ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Alt 2003-04-10, 20:42:20   #20 (im Thread / einzeln)
Demirug
3DCenter Crew & 3D-Guru
 
Benutzerbild von Demirug
 
Registriert: 2002-05-14
Beiträge: 22.430
Demirug eine Nachricht über MSN schicken
Zitat:
Originally posted by zeckensack
Die schießen aber wirklich mit Thrombosen auf Spatzen
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
Um zu verhindern das man beliebig viele Instanzen erzeugen kann macht man einfach alle (inklusive default) Konstruktor mindestens protected und das Thema ist erledigt.

Demirug ist offline   Mit Zitat antworten Beitrag zum Zitieren auswählen
Antwort

Lesezeichen
  • Dieses Thema bei Twitter speichern
  • Dieses Thema bei Facebook speichern


Forumregeln
Es ist Ihnen erlaubt, neue Themen zu verfassen.
Es ist Ihnen erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.

Gehe zu


Alle Zeitangaben in WEZ +2. Es ist jetzt 18:32:49 Uhr.


Powered by vBulletin® (Deutsch)
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.