PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C++ für Java-Programmierer


Gast
2005-10-12, 14:13:52
Hi,

ich versuche mir gerade verzweifelt etwas C++ anzueignen, weil ich in einigen Vorlesungen im nächsten Semester kleine C++-Progrämmchen schreiben muss/darf. Bisher habe ich Java drauf und meine C-Kenntnisse, die ich mir vor 5 oder 6 Jahren mal angeeignet habe, wieder fast vollständig verdrängt.

Mal ein Beispiel aus einem Lehrbuch:

Klassendeklaration:

class Ratio
{ //rationale Zahl, dargestellt durch Zähler und Nenner
public:
Ratio& malGleich(const Ratio &x);
Ratio& plusGleich(const Ratio &x);
void print();
long zaehler() { return zaehl; }
long nenner() { return nenn; }
private:
long zaehl, nenn;
void kürze();
}

Memberfunktion:

Ratio& Ratio::plusGleich(const Ratio& x)
{
zaehl = zaehl * x.nenn + nenn * x.zaehl;
nenn *= x.nenn
kuerze();
return *this;
}

1. In der Klassendeklaration steht in der Signatur des Methodenrumpfes
const Ratio &x
aber in der Implementation der Methode
const Ratio& x.

Wieso einmal das &-Zeichen an der Variable und einmal am Typ?

2. Was ist eine Memberfunktion?

3. Wieso ist die Implementation der Methode plusGleich nicht schon in der Klassendeklaration vorgenommen worden, sondern "irgendwie" gesondert?
Würde die Klassendeklaration in eine Header-Datei kommen, die Implementation der Methoden in die *.c(pp)-Dateien?
Wie mache ich kenntlich, dass die Implementation einer bestimmten Methode in einer *.C(PP)-Datei zur Deklaration einer bestimmten Klasse in einer Header-Datei gehört?

4. Was bedeutet bei
Ratio& Ratio::plusGleich (...)
der doppelte Doppelpunkt?

5. Was soll das &-Zeichen hinter dem Typ der Methode
Ratio& Ratio::plusGleich(...).

6. Was wird bei
return *this;
zurückgegeben?
Worauf 'zeigt' this?! Wieso ist vor dem this noch ein *?
Wird ein Zeiger auf die Funktion zurückgegeben? Falls, ja: Hä??


Andere Beispiele:

void ausgabe (Typ& x, FILE *wohin = stdout);

Warum wird einmal & und einmal * benutzt?
Warum steht das & am Typ, aber das * an der Variable?


void swapptr(void*& a, void*& b)
{
void* h;
h=a; a=b; b=h;
}
*kreisch* *in Tränen ausbrech* *nichts versteh*


Ich weiss selber, dass ich noch einen langen Weg zum Verständnis dieses Krampfs vor mir habe, aber es wäre dennoch sehr freundlich, wenn mir jemand diese Fragen beantworten könnte! :)

noid
2005-10-12, 14:35:10
Hi,

ich versuche mir gerade verzweifelt etwas C++ anzueignen, weil ich in einigen Vorlesungen im nächsten Semester kleine C++-Progrämmchen schreiben muss/darf. Bisher habe ich Java drauf und meine C-Kenntnisse, die ich mir vor 5 oder 6 Jahren mal angeeignet habe, wieder fast vollständig verdrängt.

Mal ein Beispiel aus einem Lehrbuch:

Klassendeklaration:

class Ratio
{ //rationale Zahl, dargestellt durch Zähler und Nenner
public:
Ratio& malGleich(const Ratio &x);
Ratio& plusGleich(const Ratio &x);
void print();
long zaehler() { return zaehl; }
long nenner() { return nenn; }
private:
long zaehl, nenn;
void kürze();
}

Memberfunktion:

Ratio& Ratio::plusGleich(const Ratio& x)
{
zaehl = zaehl * x.nenn + nenn * x.zaehl;
nenn *= x.nenn
kuerze();
return *this;
}

1. In der Klassendeklaration steht in der Signatur des Methodenrumpfes
const Ratio &x
aber in der Implementation der Methode
const Ratio& x.

Wieso einmal das &-Zeichen an der Variable und einmal am Typ?



das ist total egal... & hier oder da. egal auch beim geliebten * X-D



2. Was ist eine Memberfunktion?


eine Memberfunktion ist eine Funktio, die einer Klasse zugehörig ist.
in class {}; deklariert.



3. Wieso ist die Implementation der Methode plusGleich nicht schon in der Klassendeklaration vorgenommen worden, sondern "irgendwie" gesondert?
Würde die Klassendeklaration in eine Header-Datei kommen, die Implementation der Methoden in die *.c(pp)-Dateien?
Wie mache ich kenntlich, dass die Implementation einer bestimmten Methode in einer *.C(PP)-Datei zur Deklaration einer bestimmten Klasse in einer Header-Datei gehört?



siehe 4.



4. Was bedeutet bei
Ratio& Ratio::plusGleich (...)
der doppelte Doppelpunkt?



der DoppelteDoppelpunkt dient der Zuordnung zu einem Namespace/Klasse.
Hier ist die Fkt plusGleich der Klasse Ratio zugeordnet.




5. Was soll das &-Zeichen hinter dem Typ der Methode
Ratio& Ratio::plusGleich(...).



Es wird eine Referenz zurückgegeben, keine Kopie



6. Was wird bei
return *this;
zurückgegeben?
Worauf 'zeigt' this?! Wieso ist vor dem this noch ein *?
Wird ein Zeiger auf die Funktion zurückgegeben? Falls, ja: Hä??



this zeigt auf die Klasse selbst (also nur verwendwar innerhalb einer Memeberfunktion).




Andere Beispiele:

void ausgabe (Typ& x, FILE *wohin = stdout);

Warum wird einmal & und einmal * benutzt?
Warum steht das & am Typ, aber das * an der Variable?


Frage des Stils und der Vorlieben (stellenweise)



void swapptr(void*& a, void*& b)
{
void* h;
h=a; a=b; b=h;
}
*kreisch* *in Tränen ausbrech* *nichts versteh*


da werden 2 referenzen auf zeiger(!) übergeben und dann vertauscht.
ich finde das krank...


Ich weiss selber, dass ich noch einen langen Weg zum Verständnis dieses Krampfs vor mir habe, aber es wäre dennoch sehr freundlich, wenn mir jemand diese Fragen beantworten könnte! :)

MuLuNGuS
2005-10-12, 14:59:30
wo das & stehen sollte hängt davon ab was man gerade machen will..

ist schon ein unterschied ob man eine referenz deklariert oder die adresse einer variable übergeben will.

referenz:
int a = 100;
int& aref = a;

zeiger:
int b = 200;
int* apointer = &b;


this ist immer ein zeiger auf die instanz des objektes selber.
da es sich bei this um einen zeiger handelt und eine refernz erwartet wird muß der zeiger erst dereferenziert werden was wiederum mit dem * geschieht.

du solltest die ein gutes buch mit den grundlagen besorgen, die fragen die sich bei dir stellen kann man schwer auf die schnelle verständlich machen.
MuL

Gast
2005-10-12, 15:29:27
wo das & stehen sollte hängt davon ab was man gerade machen will..

ist schon ein unterschied ob man eine referenz deklariert oder die adresse einer variable übergeben will.

referenz:
int a = 100;
int& aref = a;

zeiger:
int b = 200;
int* apointer = &b;
Ok, ich habe schon verstanden, weshalb vor dem b ein & steht und vor dem a nicht. War halt die Frage, ob
int& aref = a;
dasselbe macht wie
int &aref = a;.
Aber offenbar ist das identisch.


this ist immer ein zeiger auf die instanz des objektes selber.
da es sich bei this um einen zeiger handelt und eine refernz erwartet wird muß der zeiger erst dereferenziert werden was wiederum mit dem * geschieht.Also ich habe noch nicht verstanden, wieso man vor eine Methode ein & schreibt.
Beispiel: Ratio& malGleich(const Ratio &x); bzw Ratio &malGleich(const Ratio &x);
Warum schreibt man nicht Ratio malGleich(const Ratio &x);? (ohne &)


Und this ist ein Zeiger auf die Instanz des Objekts selber. Dann verstehe ich den Sinn dieser Methode plusGleich nicht.

Ich habe bspw zwei Variablen ratvar1 und ratvar2 vom Typ Ratio.
Ich möchte nun die beiden Variablen addieren - dazu gibts die Membermethode plusGleich. Also schreibe ich:
ratvar1.plusGleich(ratvar2);
Innerhalb der Methode von ratvar1 wird nun etwas gerechnet und die Attribute von ratvar1 verändert:
zaehl = zaehl * x.nenn + nenn * x.zaehl;
nenn *= x.nenn
Wozu wird denn jetzt noch die Referenz auf das Objekt ratvar1 zurückgegeben? Damit passiert doch gar nichts?!

Man gibt etwas zurück, wenn man beim Methodenaufruf ein Ergebnis haben möchte, das man dann irgendwohin zuweisen kann, zum Beispiel:
x = ratvar1.plusGleich(ratvar2);
In der Methode würde ich dann ein "return <irgendein Wert>;" haben, d.h. ich gebe etwas zurück und benutze es dann weiter.

du solltest die ein gutes buch mit den grundlagen besorgen, die fragen die sich bei dir stellen kann man schwer auf die schnelle verständlich machen.
MuLJa, ich habe schon ein Buch, aber das ist entweder nicht sonderlich gut oder ich bin vmtl zu begriffsstutzig. ;)

noid
2005-10-12, 15:35:30
wenn du nur Ratio zurückgibst, dann hast du keinen lvalue, welchen man bei sowas:

ratvar1.plusGleich(ratvar2).plusGleich(ratvar3).plusGleich(ratvar4);

bräuchte.

Gast
2005-10-12, 16:16:43
wenn du nur Ratio zurückgibst, dann hast du keinen lvalue, welchen man bei sowas:

ratvar1.plusGleich(ratvar2).plusGleich(ratvar3).plusGleich(ratvar4);

bräuchte.
Äh, aha. oO


struct karte
{
float x;
float y;
} mp;

karte &verschieben(struct karte &mymap)
{
mymap.x -= 4.0 ;
mymap.y -= 2.5;
return mymap;
}

Ohne "karte &verschieben(..)" und "return mymap" könnte ich folglich sowas
verschiebe(verschiebe(mp));
nicht machen und müsste
verschiebe(mp); verschiebe(mp);
machen, um dasselbe zu erreichen?

Dann verstehe ich allerdings immer noch nicht, wozu ich das & vor dem Methodennamen brauche. ;)
Die Methode gibt einen Wert vom Typ karte zurück, womit dann weitergearbeitet werden kann: verschiebe(verschiebe(mp)).
Aber wozu ist das & nun notwendig?
Kann ich nicht einfach

karte verschiebe(struct karte &mymap) // kein &verschiebe(..)
{ ...
return mymap;
}
schreiben?

MuLuNGuS
2005-10-12, 16:26:02
das & ist doch teil des typs den die methode/funktion zurückgibt..


Ratio& NameDerMethode(int test);

diese methode erwartet einen int als parameter und gibt eine referenz auf Ratio zurück.

Gast
2005-10-12, 16:28:55
Ach, vergesst es: Das ist das alte Lied von Call-by-Reference und Call-by-Value und ich bin mal wieder drauf reingefallen bzw habe mich davon verwirren lassen. *schande*

Danke für die Unterstützung. :)

Baalzamon
2005-10-12, 18:02:21
Wenn du noch weitere Fallstricke vermeiden möchtest, dann schau dir doch mal diese (http://www.cs.brown.edu/courses/cs123/javatoc.shtml) Seite an, da werden die Unterschiede zwischen Java/C++ sehr schön dragestellt.
Hier (http://www-ali.cs.umass.edu/~mckinley/377/labs/c++_for_java_programmers.html) gibts das Ganze auch nochmal nicht ganz so ausführlich.

Gast
2005-10-12, 18:45:26
1. In der Klassendeklaration steht in der Signatur des Methodenrumpfes
const Ratio &x
aber in der Implementation der Methode
const Ratio& x.

Wieso einmal das &-Zeichen an der Variable und einmal am Typ?ist egal, kannste machen wie du lustig bist.

2. Was ist eine Memberfunktion?das solltest du aus Java kennen...

3. Wieso ist die Implementation der Methode ach, was ne Methode ist weißt du aber? Memberfunktion ist ein anderes Wort dafür.

plusGleich nicht schon in der Klassendeklaration vorgenommen worden, sondern "irgendwie" gesondert?man kann's auch direkt machen, wenn mal will. War aber auch in C schon so, daß man die Implementierung einer Funktion von ihrer Deklaration trennen konnte.
Ist z.B. bei modularer Programmierung von Vorteil, wenn der Sourcecode über mehrere Sourcecodedateien verteilt ist. Dann bindet man die Header-Datei mit der Deklaration überall ein wo sie gebraucht wird, die Implementierung macht man dagegen nur einmal.

Würde die Klassendeklaration in eine Header-Datei kommen, die Implementation der Methoden in die *.c(pp)-Dateien?bingo.

Wie mache ich kenntlich, dass die Implementation einer bestimmten Methode in einer *.C(PP)-Datei zur Deklaration einer bestimmten Klasse in einer Header-Datei gehört? du schreibst Klassenname:: vor den Namen der Memberfunktion (der Methode).

4. Was bedeutet bei
Ratio& Ratio::plusGleich (...)
der doppelte Doppelpunkt?der bedeutet die Antwort auf deine vorherige Frage.

5. Was soll das &-Zeichen hinter dem Typ der Methode
Ratio& Ratio::plusGleich(...). das soll, daß die Methode nicht ein Objekt (eine Instanz der Klasse Ratio) zurückgibt, sondern nur eine Referenz auf ein solches. In Java und Delphi wird so was standardmäßig gemacht, daher wird da kein Referenzoperator verwendet.

6. Was wird bei
return *this;
zurückgegeben?this ist ein Pointer auf die aktuelle Instanz der Klasse. * dereferenziert this, also ist *this die aktuelle Instanz. Da die Funktion aber nur eine Referenz zurückgibt und kein Ratio-Objekt selbst, wird letzendlich eine Referenz auf das aktuelle Objekt zurückgegeben.

Worauf 'zeigt' this?! auf das aktuelle Objekt.

Wieso ist vor dem this noch ein *?weil eine Referenz auf das Objekt zurückgegeben wird und nicht eine Referenz auf einen Pointer auf das Objekt. Daher wird this noch eben dereferenziert. Referenz auf Pointer ginge auch, das sähe dann so aus:

Ratio& *Ratio::plusGleich...

Wird ein Zeiger auf die Funktion zurückgegeben?nee, auf's Objekt.


Andere Beispiele:

void ausgabe (Typ& x, FILE *wohin = stdout);

Warum wird einmal & und einmal * benutzt?daß man FILE* und nicht FILE& nimmt, liegt wohl daran, daß man

1) in der Funktion, von der aus ausgabe aufgerufen wird, vorher Funktionen aufruft, die den Rückgabetype FILE* haben (z.B. fopen()), und deren Rückgabewert man dann einfach an ausgabe weiterreicht, z.B.

FILE* pFile = fopen(/*...*/);
ausgabe(pFile);


2) in der Funktion ausgabe weitere Funktionen benutzt, die einen Parameter vom Typ FILE* erwarten, z.B. fprintf().

Es wäre reichlich unsinnig, erst von FILE* zu FILE& und dann wieder zu FILE* zu konvertieren.

Warum steht das & am Typ, aber das * an der Variable?weil der Autor des Buches Spaß dran hatte.



void swapptr(void*& a, void*& b)
{
void* h;
h=a; a=b; b=h;
}
*kreisch* *in Tränen ausbrech* *nichts versteh*für solche Fälle gestehe ich ein, daß die Verwendung von typedef auch sinnvoll sein kann.

typedef void* PVOID;

//...

void swapptr(PVOID& a, PVOID& b)
{
PVOID h;
h=a; a=b; b=h;
}
so besser?

Gast
2005-10-12, 19:36:15
das solltest du aus Java kennen...

ach, was ne Methode ist weißt du aber? Memberfunktion ist ein anderes Wort dafür.Naja, Memberfunktion habe ich heute zum ersten Mal gehört, Methode höre ich ständig.
Kann ja wieder ein weiterer Knüppel sein, der einem von C++ zwischen die Beine geworfen wird, um bequemes Programmieren zu unterbinden. ;)

MuLuNGuS
2005-10-13, 08:42:46
Zitat:
Zitat von Gast
plusGleich nicht schon in der Klassendeklaration vorgenommen worden, sondern "irgendwie" gesondert?

man kann's auch direkt machen, wenn mal will. War aber auch in C schon so, daß man die Implementierung einer Funktion von ihrer Deklaration trennen konnte.
Ist z.B. bei modularer Programmierung von Vorteil, wenn der Sourcecode über mehrere Sourcecodedateien verteilt ist. Dann bindet man die Header-Datei mit der Deklaration überall ein wo sie gebraucht wird, die Implementierung macht man dagegen nur einmal.


es gibt einen gravierenden unterschied wenn die implementierung teil der header-datei ist.
in dem fall handelt es sich um eine inline-methode, das hat nix mit modularer programmierung zu tun.