Dringend C++ Nachhilfe benötigt! - mit Bezahlung

Diskussionen rund um Themen und Veranstaltungen des 3. Bachelor-Semesters

Moderator: (M) Mod.-Team Allgemein

Benutzeravatar
NightStalker
TalkING. Champion
TalkING. Champion
Beiträge: 891
Registriert: Mo, 21. Okt. 02, 20:40
Wohnort: Downloadbereich

Beitrag von NightStalker » Di, 01. Mär. 11, 23:33

Ja prinzipiell geht das, aber man macht das eigentlich nicht aus Designgründen. Es gibt ein paar Sachen, da muß man mit Pointern auf Objekte arbeiten (Stichwort Polymorphismus z.B., weiß nicht, ob das noch kommt).
-- Chrząszcz brzmi w trzcinie w Szczebrzeszynie.
-- 好好学习,天天向上!

Formelsammler
TalkING. Superposter
TalkING. Superposter
Beiträge: 297
Registriert: Mi, 17. Feb. 10, 15:55

Beitrag von Formelsammler » Di, 01. Mär. 11, 23:43

beides ist richtig.

Deine Klasse Nahrung kannst du vereinfacht gesagt wie int , double usw. behandeln.

Die Unterschiede zwischen den beiden Varianten sind folgendes:

Code: Alles auswählen

Nahrung *essen = new Nahrung();
hier ist essen ein Zeiger, der auf den Anfang eines Speicherbereichs "vom Typen Nahrung" auf dem Heap zeigt.

Dieser Speicherbereich muss nach der Nutzung freigegeben werden mit

Code: Alles auswählen

delete essen;
man greift auf die Funktionen und Variablen von essen zu entweder so

Code: Alles auswählen

(*essen).Funktionxyz();
oder so

Code: Alles auswählen

essen->Funktionxyz();
also im Allgemeinen gesagt ... das ist eine dynamische Variable vom Typ Nahrung. Der Zeiger essen könnte später auf Wunsch des Programmierers auf einen anderen Bereich zeigen.

Code: Alles auswählen

int main() { 
     Nahrung essen;   //Objekt essen erstellt 
     essen. ...();    //Operation ausführen an Objekt essen 
     return 0; 
}
dies hier ist eine lokale Variable, die auf den Stack gespeichert und automatisch nach Verlassen des Gültigkeitsbereichs freigegeben wird.

also essen ist kein Zeiger, deshalb greift man auf die Funktionen und Variablen von essen mit dem Punkt zu.

Code: Alles auswählen

essen.Funktionxyz();
Meinem Vorredner stimme ich zu.

dolacose
TalkING. Fan
TalkING. Fan
Beiträge: 37
Registriert: Sa, 20. Mär. 10, 10:57

Beitrag von dolacose » Mi, 02. Mär. 11, 00:30

wenn ich also nur in dem

Code: Alles auswählen

int main() Block
bleibe, dann kann ich also ruhig das untere nehmen, oder?
Und wenn ich in mehreren "Ebenen", also Blöcken oder gar Schnittstellen handtiere, dann wäre eine Dynamische Variante mittels Zeiger besser?! :)

Gute Nacht schonmal! Und wiedermal Danke!!!!
Can't wait the rythm...

Formelsammler
TalkING. Superposter
TalkING. Superposter
Beiträge: 297
Registriert: Mi, 17. Feb. 10, 15:55

Beitrag von Formelsammler » Mi, 02. Mär. 11, 01:14

Hier gibt's ein kleines Missverständnis ...

Die beiden Varianten können sowohl auserhalb der Blöcke (global) oder innerhalb der Blöcke (lokal) implementiert werden.

Auf globale Zeiger oder Variable kann von allen Blöcken zugegriffen werden, während die lokalen nur im eigenen Block sichtbar sind.

Ob du einen Zeiger (die erste Variante) oder eine Variable (die zweite Variante) deklarieren willst, hat nichts mit dem Gültigkeitsbereich zu tun.

Man verwendet die Zeiger in der Regel für Arrays, Polymorphie , Funktionsparameter (in bestimmten Fällen) .. usw. und verwendet Variable in den allermeisten Fällen, wo keine "dynamischen Eigenschaften (Größenänderung z. B.) " verlangt sind.

Ebenfalls gute Nacht.

Benutzeravatar
stereo
Uni-Mitarbeiter
Uni-Mitarbeiter
Beiträge: 1260
Registriert: Sa, 26. Nov. 05, 21:12
Kontaktdaten:

Beitrag von stereo » Mi, 02. Mär. 11, 08:20

Wenn du dir eine Funktion vorstellst, die ein Objekt deiner Klasse als Parameter erwartet, wird das evtl leichter zu verstehen.

Code: Alles auswählen

int handleEssen(Nahrung *essen) 
{
    ...
    return 0
}
Diese Funktion arbeitet auf einem Pointer auf Nahrung (call by reference). Das Übergebene Objekt, wie Formelsammler schon gesagt hat, liegt auf dem Heap deines Programms und ist daher, wenn ein Block einen Pointer darauf bekommt, für diesen Block sichtbar, auch wenn er es nicht erstellt hat. Das Objekt wird also von dieser Funktion manipuliert und alle anderen Blöcke, die eine Referenz darauf halten, sehen die Veränderungen.

Code: Alles auswählen

int handleEssen(Nahrung essen)
{
    ...
    return 0
}
Diese Funktion arbeitet auf einem eigenen Objekt (call-by-value). Das übergebene Objekt liegt auf dem Stack und jede Manipulation geht verloren, wenn das fertige essen nicht wieder zurückgegeben wird. Z.B. so:

Code: Alles auswählen

Nahrung handleEssen(Nahrung essen)
{
...
return essen;
}
Welche Variante du wählst hängt stark von deiner aktuellen Anforderung ab. Brauchst du eine Klasse nur, um lokal Arbeit für dich zu verrichten, kannst du sie lokal instanziieren. Stell dir eine Klasse vor, die dir Methoden bietet, das aktuelle Datum formatiert auszugeben. Diese Klasse hat keinen Zustand, sondern ausschliesslich Methoden, die bei jedem Auruf das gleiche Ergebnis liefern. Diese Klasse brauchst du nicht auf dem Heap, weil sie nichts zum Zustand deines Programms beiträgt. Sie ist zu behandeln wie eine lokale Variable.
Ein Objekt, das aber z.B. Daten aus einer Datenbank hält ist zustandsbehaftet. Viele Methodenaufrufe oder externe Manipulationen verändern seine Daten und ist es in den wenigsten Fällen sinnvoll, diese Daten nur lokal in einer Funktion zu halten. Normalerweise willst du sie innerhalb deines Programms hin- und herreichen. Darum erstellst du das Objekt auf dem Heap und übergibst es zur Manipulation, wo es gebraucht wird.

Und Pointer haben noch einen ziemlich anschaulichen Vorteil wenn es um Manipulation durch Funktionen geht:

Code: Alles auswählen

int essenEinkaufen(Nahrung *essen)
{
    int i = 0;
    while (!essen->genugDa())
    {
        essen->kaufeNeu();
        i++;
    }
    return i;
}
Diese Funktion operiert auf einem Pointer auf Nahrung. Sie verändert das essen Objekt indem sie eine Methode aufruft, die neues essen einkauft. Nebenbei speichert sie, wie oft sie einkaufen war und gibt diesen Wert zurück. Auf diese Weise erhalten aufrufenden Instanzen einen Hinweis auf die Art der Veränderun am Objekt. Da hier ein Pointer übergeben wird und keine lokale Kopie, muss nicht das Objekt selbst zurückgegeben werden sondern wird direkt in seinem eigenen Speicher manipuliert. Der Rückgabetyp ist int und gibt einen Hinweis, wie oft eingekauft werden musste.

Antworten