Forum: PC-Programmierung Zeigerproblem


von Gregor H. (Gast)


Lesenswert?

Hallo,
also ich hab folgendes Problem, ich hab die Klassen Person, Mann und 
Frau.
Ich moechte nun ein Programm schreiben (in C++) in der entweder ein Mann 
oder eine Frau die ganzen Funktionen
ausfuehren und dies soll ueber einen Button entschieden werden.
Ich hab jetzt daran gedacht das Mann und Frau von Person erben, ich ein 
Objekt von Person erzeug und
dann einen Zeiger zwischen einem Mann und einem Frau Objekt hin und her 
bieg. Geht das? Wenn ja wie implementier ich das?
Das Programm soll spaeter auch noch andere Klassen (aehnlich wie Frau 
und Mann :-)) erhalten, deshalb soll das Programm
moeglichst einfach zu aendern sein und ich moechte nicht jede Funktion 
mit einem if Button abfragen welcher Button gedrueckt ist.
Hoffe ihr koennt mir helfen und danke schonmal im Vorraus.

Gruesse Gregor

von Klaus W. (mfgkw)


Lesenswert?

Welche Klasse und wann ist Abgabe?

von Gregor H. (Gast)


Lesenswert?

:-) Nope leider nicht.
Bin Student und lern grad C++.
Ist keine Klassenarbeit etc.

von Klaus W. (mfgkw)


Lesenswert?

Dann würde ich doch mal ein vernünftiges Buch über C++ nahelegen.

Es ist etwas einfacher, wenn du das erstmal durcharbeitest, als
wenn man hier alle Grundlagen einzeln vorkauen muß.

Das ist nicht böse gemeint, aber so macht es doch keinen Sinn.

von Gregor H. (Gast)


Lesenswert?

Danke fuer die Hilfe ...
Ich kenn mich mit Zeigern auf Arrays usw. aus.
Nur weiss ich halt nicht wie das mit Objekten funktioniert.
Muessen Mann und Frau die gleichen Funktionen haben damit ich einen 
Zeiger auf Person legen kann und die Funktion dann ueber Person aufruf?
Die einzelnen Funktionen von Mann und Frau unterscheiden sich naemlich 
inhaltlich.

von Nobody (Gast)


Lesenswert?

Aber Du kennst Dich ganz offensichtlich mit C++ nicht aus.
Normalerweise legt niemand in einer Instanz des Elternobjektes einen 
Zeiger auf die Instanz eines Kindobjektes an. Wozu auch? Das Kinndobjekt 
erbt ja alle Eigenschften.
Beschreibe mal genauer die Problemstellung.

von Klaus W. (mfgkw)


Lesenswert?

Gregor H. schrieb:
> Ich kenn mich mit Zeigern auf Arrays usw. aus.
> Nur weiss ich halt nicht wie das mit Objekten funktioniert.

Dann würde ich doch mal ein vernünftiges Buch über C++ nahelegen.

von Gregor H. (Gast)


Lesenswert?

Problem ist einfach ich hab 2 Objekte Mann und Frau und jeder hat z.B. 
die Methode laufen()
also ich hab in meinem Code ... Mann.laufen() ...   und jezt will ich 
das einfach durch Frau.laufen() austauschen.
Ohne den Code zu veraendern und ich hab halt gedacht das ich 
Person.laufen() in den Code schreib und dann von Person
einen Zeiger auf Mann bzw. Frau bieg.
Hoff ich konnts jetzt einigermassen erklaeren und ihr koennt mir helfen.
Sorry fuer die Missverstaendnisse.

von Klaus W. (mfgkw)


Lesenswert?

Gregor H. schrieb:
> ... die Missverstaendnisse.

Diese wiederum legen den Gebrauch eines Buches nah.

Tip: es geht nicht durch Umbiegen von Zeigern.

von Gregor H. (Gast)


Lesenswert?

Ja wie loes ich das dann? Von mir aus sag mir halt nur das Stichwort wie 
ich so ein Problem angehen kann, dann schau ich selber nach ...

von Flo S. (tuxianer)


Lesenswert?

Also das mit der Vererbungshierarchie ist schon richtig. Du lässt Mann 
bzw. Frau von Person erben.
Was du jetzt willst, habe ich jetzt so interpretiert, dass du eine 
Möglichkeit suchst einen Zeiger wahlweise auf ein Mann oder Frau Objekt 
zeigen zu lassen. Da geht mit Polymorphismus.

von Gregor H. (Gast)


Lesenswert?

Endlich mal ne brauchbare Antwort.
Danke!

von Daniel (Gast)


Lesenswert?

manche skriptsprachen wie Python und Ruby haben duck-typing (siehe wiki)
C++ muss zumindest ist-ein Relationen zwischen Typen zur Compilierzeit
wissen.

Mensch hat 2 Arme.
Mann ist ein Mensch. (hat also 2 Arme)
Frau ist ein Mensch. (dito)

von Michael II (Gast)


Lesenswert?

Japp, Polymorphie ist das Stichwort. Lang ists her mit C++, aber ich 
versuche es mal mit dem Person Mann Frau Beispiel. Die Konstruktoren 
etc. lass ich weg.

1
class Person
2
{
3
public:
4
   string name;
5
   virtual void bewegen(Person *ziel){cout << "Ich " << this->name << " gehe zu " << ziel->name << endl;}
6
};
7
class Mann : public Person{};
8
class Frau : public Person{};
9
class Baby : public Mann
10
{
11
   void bewegen(Person *ziel){cout << "Ich " << this->name << " krabbel zu " << ziel->name << endl;}
12
};
13
14
void main()
15
{
16
   Mann *peter = new Mann("Peter");
17
   Frau *renate = new Frau("Renate");
18
   Baby *martin = new Baby("Martin");
19
20
   peter->bewegen(renate);
21
   renate->bewegen(martin);
22
   martin->bewegen(peter);
23
}

>> Ich Peter gehe zu Renate
>> Ich Renate gehe zu Martin
>> Ich Martin krabbel zu Peter

Viel Spass beim rumspielen!

von Karl H. (kbuchegg)


Lesenswert?

Michael II schrieb:

> Viel Spass beim rumspielen!

Zu einem guten Polymorphiebeispiel würde das, wenn du folgendes machst
1
void tellItToMove( Person* pers, Person* to )
2
(
3
  pers->bewegen( to ); 
4
)
5
6
void main()
7
{
8
   Mann *peter = new Mann("Peter");
9
   Frau *renate = new Frau("Renate");
10
   Baby *martin = new Baby("Martin");
11
12
   tellItToMove( peter, renate );
13
   tellItToMove( renate, martin );
14
   tellItToMove( martin, peter );
15
}

Die Funktion tellItToMove hat keinen blassen Schimmer davon, wer oder 
was pers ist. Trotzdem landet der Funktionsaufruf bewegen immer bei der 
richtigen Klasse.

Bei deinem Beispiel ist das 'Problem' darin, das du mit expliziten Mann, 
Frau und Baby Pointern hantierst. Genau darum geht es ja bei 
Polymorphie: Das der genaue Typ des Objektes beim Aufruf der jeweiligen 
Funktion zur Compiletime eben nicht bekannt ist. Dein Beispiel würde 
auch ohne Polymorphie (also ohne virtuelle Funktionen) funktionieren.

von Michael II (Gast)


Lesenswert?

Ok, ich glaube zu verstehen was du meinst. Ich habe die Polymorphie erst 
in der bewegen()-Funktion vollzogen, du aber außerhalb der abgeleiteten 
Klassen, was formal richtig ist, sehe ich das richtig? Und du hast 
recht, die Verwendung von 'virtual' ist nur nötig bei der Verwendung von 
Kopien der Person-Klasse, in diesem Fall also nicht da Person* benutzt 
wurde (frühe/späte Bindung). Wie schnell man doch vergisst, wenn man es 
nicht anwendet. :-)

MfG

von Klaus W. (mfgkw)


Lesenswert?

@Michael II:
In deinem Beispiel gibt es keine Polymorphie.

Die kommt erst ins Spiel, wenn an einer Stelle eine Basisklasse
bekannt ist (Person), in Wirklichkeit aber ein Objekt einer
davon abgeleiteten Klasse (Mann, Frau, ...) vorliegt.
Falls die entsprechenden Methoden virtual sind, werden dann
korrekt die der abgeleiteten Klasse aufgerufen und nicht die
der Basisklasse.

In dem KHB-Beispiel:
tellItToMove() glaubt, eine Person zu haben und kann nicht
sehen, ob es zur Laufzeit wirklich eine Person ist, oder
etwas davon abgeleitetes.
Der Compiler kann also beim Aufruf von pers->bewegen()
nicht wissen, was er tatsächlich aufruft (Person::bewegen(),
Mann::bewegen(), Frau::bewegen(), ...).
Wäre bewegen() nicht virtual, würde in jedem Fall
Person::bewegen() genommen werden.
Durch das virtual dagegen wird Code so erzeugt, daß zur
Laufzeit dem jeweils aktuellen Objekt entnommen, welche
Methode dazu gehört.
Das ist nur möglich, wenn peter, renate und martin entweder
als Zeiger oder Referenz übergeben werden.

Michael II schrieb:
> Und du hast
> recht, die Verwendung von 'virtual' ist nur nötig bei der Verwendung von
> Kopien der Person-Klasse

Wenn peter, renate und martin als Kopie übergeben werden
(also nicht Zeiger, nicht Referenz) ist virtual eben
nicht wirksam.
Dann passiert Folgendes: Beim Aufruf werden peter etc. in
eine Person gecastet.
Innerhalb der aufgerufenen Funktion ist es damit Person,
und (unabhängig von virtual oder nicht) wird in jedem Fall
Person::bewegen() verwendet; die Kopie ist ja nicht
mehr Mann oder Frau.

von Michael II (Gast)


Lesenswert?

Danke für die Aufklärung. Ich habe grad mein altes Skript ausgebuddelt 
und nochmal nachgeschlagen. Es wird etwas unglücklich erklärt, aber 
richtig. Ich hatte es anscheinend nie richtig verstanden. Ich muss 
zugeben nie ein C++ Buch bessesen zu haben, das wird sich ändern.

MfG

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.