Warum deklariert man Zeiger auf Klassen?
-
Hallo, ich bin neu hier (ebenso in C++) und habe gleich meine erste Frage.
-1) Warum deklariert man eigentlich Zeiger (auch Referenzen) auf Klassen?
*z.B.
Cat pCat=new Cat;Wenn ich einen Zeiger auf eine Ganzzahl, also Integer deklariere, dann weiß ich dass dieser Zeiger nur ganze Zahlen aufnehmen wird.
-2) Was nimmt dann der Zeiger auf die Klasse auf?
Ich nehme mal an nur dessen Methoden und Variablen die in der Klasse deklariert habe?
also:
class Klasse
{
public:
GetDate() const {return itsDate;};
SetDate(int date) {itsDate=date;};
private:
int itsDate;
}Das heißt also ich könnte dem Zeiger nur etwas mit GetDate(), SetDate(date) zuweisen. (itsDate ist ja private)
Jedoch kapiere ich immer noch nicht weshalb es sinnvoll ist Zeiger auf Klassen zu deklarieren.
-3) Was habe ich denn davon für Vorteile (bzw. was ist anders) gegen über einer Klasse die auf int deklariert ist? Ist das eine weitere Hilfe für die Fehlerfindung wie z.B. const?Ebenso sperrt es sich in meinem Kopf, wenn ich folgende Funktionsdefinition sehe:
1) SimpleCat FunctionOne(SimpleCat theCat);
bzw.
2) SimpleCat *FunctionTwo(SimpleCat *theCat);Was passiert hier?
Ich habe als Rückgabetyp die Klasse SimpleCat, wo normalerweise int usw. stehen würde.
-4) Was liefert mir denn die Funktion da zurück? Wieder den ganzen Inhalt eines bestimmten Klassenobjekts z.B. SimpleCat meineKatze;?
-5) Und vor allem, was für ein Nutzen hat diese Funktion?
-6) Warum übergibt man einer Funktion eine Klasse bzw. Klassenobjekt?Ich bedanke mich für eure Mühe und hoffe nicht zuviel Unsinn geschrieben zu haben

johnson
-
Du solltest dir ein Grundlagenbuch besorgen... unbedingt! Es gibt viel zu erklären...
Um dich nicht verzweifeln zu lassen:
- Mit dem Operator new legt man dynamisch Objekte an. In deinem Beispiel ein Objekt des Typs Klasse Cat. Somit bestimmst DU wann das Objekt mit dem Operator "delete" wieder zerstört wird, und nicht der Gültigkeitsbereich (Aber Achtung, Zerstörungen der Zeigerobjekte werden natürlich weiterhin vom Gültigkeitsbereich beeinflusst). In dem Fall deshalb ein Zeiger, da "new" die Adresse des eben angelegten Objektes liefert.
Weiters kannst du zur Laufzeit einen Vektor mit bestimmter Anzahl von Elementen erzeugen. Das funktioniert nicht mit statischen Vektoren. zB:
int numObjects = 100;
Cat *pCat = new Cat[numObjects]; // 100 Cat-Objekte erzeugen-
Was er aufnimmt (adressiert)? Na ein Objekt der Klasse natürlich

Zeiger auf Klassen sind wie Zeiger auf elementare Typen. -
Eine Klasse, die auf int deklariert ist??
SimpleCat FunctionOne(SimpleCat theCat);
Hier wird der Funktion ein Objekt der Klasse "SimpleCat" übergeben, und die Funktion gibt auch ein eben solches Objekt zurück.SimpleCat *FunctionTwo(SimpleCat *theCat);
Hier wird der Funktion die Adresse eines Objekts der Klasse "SimpleCat" übergeben, und die Funktion gibt einen Zeiger auf ein eben solches Objekt zurück.-
Wie eben erwähnt, die erste Funktion liefert dir ein Objekt der Klasse SimpleCat und die zweite Funktion einen Zeiger auf ein Objekt der Klasse SimpleCat zurück.
Bei der ersten Funktion wird das Objekt bei der Übergabe kopiert, und beim Zurückliefern wieder kopiert, das heißt du hast zwei Kopien und mindestens drei eigene Objekte.
Bei der zweiten Funktion wird das Objekt bei der Übergabe adressiert, und die Funktion greift auf das soeben übergebene Objekt zu, und nicht auf eine Kopie dessen. Dies spart natürlich Zeit und ermöglicht weiterhin den direkten Zugriff auf das übergebene Objekt und nicht auf dessen Kopie. Weiters wird ein Zeiger auf das zurückgegebene Objekt geliefert, also findet hier wieder keine Kopie statt und der zurückgegebene Zeiger greift direkt auf das Objekt zu, welches zurückgegeben wurde. -
Kann ich nicht wissen

-
Na weil die Funktion vielleicht mit dem Klassenobjekt arbeiten möchte

MfG
- Mit dem Operator new legt man dynamisch Objekte an. In deinem Beispiel ein Objekt des Typs Klasse Cat. Somit bestimmst DU wann das Objekt mit dem Operator "delete" wieder zerstört wird, und nicht der Gültigkeitsbereich (Aber Achtung, Zerstörungen der Zeigerobjekte werden natürlich weiterhin vom Gültigkeitsbereich beeinflusst). In dem Fall deshalb ein Zeiger, da "new" die Adresse des eben angelegten Objektes liefert.
-
Ein Zeiger nimmt immer nur eine Adresse auf, egal ob er auf ein int zeigt oder eine Klasse.
-
@johnson79: Für den Anfang ist es vllt hilfreich, es etwas weniger technisch zu sehen. Wenn du ein Objekt OHNE Zeiger an eine Funktion übergibst, dann wird das komplette dicke, fette Objekt (wobei dick und fett bei Katzen ja meistens stimmt) kopiert. Übergibst du hingegen nur einen Zeiger (kann man sich vorstellen wie eine Art ID) auf das Objekt, dann ersparst du dir komplett die ganze Kopiererei. In der Funktion kannst du dann dennoch mit Hilfe der ID (Zeigers) auf das Objekt zugreifen.
-
johnson79 schrieb:
-1) Warum deklariert man eigentlich Zeiger (auch Referenzen) auf Klassen?
*z.B.
Cat pCat=new Cat;Wenn ich einen Zeiger auf eine Ganzzahl, also Integer deklariere, dann weiß ich dass dieser Zeiger nur ganze Zahlen aufnehmen wird.
Es wird für dich nicht unbedingt mit deinen Kenntnisstand verständlich sein, aber neben der erwähnten dynamischen Speicherallozierung, haben Zeiger/Referenzen noch eine weitere Bedeutung.
Nehmen wir mal an du hast mehrere Säugetiere. Neben Katzen auch Hunde. Nun haben Säugetiere aber auch Gemeinsamkeiten (z.B. das sie lebendgebährend sind), und das sie irgendwelche Laute von sich geben können. Mit Zeigern/Referenzen kannst du auch die einzelnen Tiere über ihre Gemeinsamkeiten verwenden:
#include <iostream> class Saeugetier { public: virtual void GibLaut() = 0; virtual ~Saeugetier() {}; }; class Katze : public Saeugetier { public: virtual void GibLaut() { std::cout << "Miau" << std::endl; } }; class Hund : public Saeugetier { public: virtual void GibLaut() { std::cout << "Wau" << std::endl; } }; int main() { Katze pussycat; Hund werdackel; pussycat.GibLaut(); werdackel.GibLaut(); Saeugetier* pTier = &pussycat; pTier->GibLaut(); pTier = &werdackel; pTier->GibLaut(); }Du kannst also die Katze und den Hund über die Basisklasse ansprechen. Dies geht aber nur mit Zeigern oder Referenzen.
Praktisches Beispiel wo man es einsetzt: Nehmen wir an du hast ein Vektororientiertes Zeichenprogramm. Jedes mal wenn du ein Symbol (egal ob nun Kreis, Viereck...) malst, wird dies in eine Liste von Grafikobjekten (Basisklasse) eingefügt [dynamische Speicherallozierung]. Wenn du eins davon nimmst und verschiebst kann nun über eine virtuelle Funktion der Basisklasse (Nehmen wir mal "void Move(long deltaX, long deltaY)" als Beispiel die Funktion der Konkreten Klasse (wie Kreis) ausgeführt werden, ohne sich darüber Gedanken zu machen was für eine Art von Klasse es ist [Polymorphie].
cu André
-
Hallo an alle die geantwortet haben...
erstmal vielen Dank für die Antworten...
Ein Grundlagenbuch besitze ich bereits "C++ in 21 Tagen". Es ist nur so, dass ich einfach keinen Zugang finden konnte zu diesem Problem...irgend ein Aspekt bremst meinen Kopf ständig aus und ich komm nicht dahinter was. Ich werd mir eure Antworten mal genauestens anschauen und in Verbindung mit dem Buch nochmals durcharbeiten. Sollte ich zu einem Ergebnis kommen dann bedanke ich mich nochmals ausführlich
Vor 10 Jahren etwa habe ich bereits Fachinformatiker gelernt...jedoch mit der Priorität auf VB. Dummerweise behandelt VB (oder zumindestens wir nicht) keine Objekte und somit ist das für mich absolutes Neuland.
Daher hoffe ich, dass ihr mich mit euren Antworten ein Stückchen näher an mein Ziel gebracht habt.
Danke also nochmals
johnson
-
doch VB behandelt auch objekt
grüßeDie Zeigergeschichte ist rel. einfach:
mit "new" ->
x *Zeiger= new x;erzeugst du ein objekt im speicehr, wo bei die Adresse im speicher des objekt durch "ZEiger" repräsentiert wird.
nun kannst du den zeiger in deinem Programm rumreichen etc. und hast so quaise immer direkteine referenzt auf das objekt im speicher.
durch
delete Zeiger;wird das objekt wieder ausm speicher gelöscht.