[C++] Pointer auf Klassenmethode nicht möglich?

M

mdaniela

Neues Mitglied
Thread Starter
Dabei seit
03.03.2006
Beiträge
16
Reaktionspunkte
0
Hallo Community!

Ich bin noch C++ Neuling und erlerne mir die Sprache Schritt für Schritt auf meinem Mac. Ich bin nun auf ein Beispiel gestoßen, in dem ich einen Pointer erzeuge, der auf eine Klassenmethode zeigt.

Das Beispiel stammt aus dem Buch "C++ in 21 Tagen" - eher auf Windows ausgerichtet - und lässt sich auf Mac nicht kompelieren.

Meine Frage: Muss ich einfach anders an das Beispiel rangehen oder gibt's unter Mac keine Pointer auf Klassenmethoden? Zweiteres kann ich mir kaum vorstellen ...

[Beispiel siehe unten]
Z 66 + 67 bringen in xCode folgende Fehlermeldung:
error: invalid use of non-static member function 'virtual void Animal::speak() const'
error: cannot convert 'void ( Animal:: ) ()const' to 'void (Animal::*)()const' in assignment


#include <iostream.h>
4:
5: class Mammal
6: {
7: public:
8: Mammal():itsAge(1) { }
9: virtual ~Mammal() { }
10: virtual void Speak() const = 0;
11: virtual void Move() const = 0;
12: protected:
13: int itsAge;
14: };
15:
16: class Dog : public Mammal
17: {
18: public:
19: void Speak()const { cout << "Wuff!\n"; }
20: void Move() const { cout << "Bei Fuß gehen ...\n"; }
21: };
22:
23:
24: class Cat : public Mammal
25: {
26: public:
27: void Speak()const { cout << "Miau!\n"; }
28: void Move() const { cout << "Schleichen...\n"; }
29: };
30:
31:
32: class Horse : public Mammal
33: {
34: public:
35: void Speak()const { cout << "Wieher!\n"; }
36: void Move() const { cout << "Gallopieren...\n"; }
37: };
38:
39:
40: int main()
41: {
42: void (Mammal::*pFunc)() const =0;
43: Mammal* ptr =0;
44: int Animal;
45: int Method;
46: bool fQuit = false;
47:
48: while (fQuit == false)
49: {
50: cout << "(0)Beenden (1)Hund (2)Katze (3)Pferd: ";
51: cin >> Animal;
52: switch (Animal)
53: {
54: case 1: ptr = new Dog; break;
55: case 2: ptr = new Cat; break;
56: case 3: ptr = new Horse; break;
57: default: fQuit = true; break;
58: }
59: if (fQuit)
60: break;
61:
62: cout << "(1)Sprechen (2)Bewegen: ";
63: cin >> Method;
64: switch (Method)
65: {
66: case 1: pFunc = Mammal::Speak; break;
67: default: pFunc = Mammal::Move; break;
68: }
69:
70: (ptr->*pFunc)();
71: delete ptr;
72: }
73: return 0;
74: }

Bin für jede Hilfe dankbar!
 
Du kannst in C++ keinen Zeiger auf eine (nicht statische) Klassenfunktion haben, da diese immer ein Teil eines Objektes ist, d.h. es gibt nicht *die* Methode "Speak" der Klasse Mammal, sondern jedes Objekt hat seine eigene Methode "Speak". (Eine statische Klassenfunktion dagegen existiert einmal für die Klasse und ist nicht an ein Objekt gebunden, auf eine solche könntest du einen Zeiger setzten.)
Ein Zeiger auf eine nicht statische Klassenmethode macht auch keinen Sinn, man benötigt einen Zeiger auf ein Objekt, dann kommt man schon an die zugehörige Methode: In deinem Beispiel bräuchtest du einen Zeiger auf ein Mammal (z. B. "Mammal* Tier") und könntest dann mit Tier->Speak() oder Tier->Move() die Methoden des entsprechenden Objekts aufrufen.
 
Vielen Dank für die flotte Antwort! Klingt alles sehr plausibel, ist auch genau so im Buch beschrieben. Sehr komisch, dass dann ein nicht funktionierentes Programm im Buch abgedruckt wurde.
Selbst die Ausgabe steht darunter:
(0)Beenden (1)Hund (2)Katze (3)Pferd: 1
(1)Sprechen (2)Bewegen: 1
Wuff!
(0)Beenden (1)Hund (2)Katze (3)Pferd: 2
(1)Sprechen (2)Bewegen: 1
Miau!
(0)Beenden (1)Hund (2)Katze (3)Pferd: 3
(1)Sprechen (2)Bewegen: 2
Galoppieren...
(0)Beenden (1)Hund (2)Katze (3)Pferd: 0
 
türlich geht das
den Code werde ich mir heute nicht mehr anschauen, morgen werd ich mal drüberschauen -- wenns bis dahin kein anderer getan hat ;)
 
Zeile 66 & 67 folgendermaßen ändern:

case 1: pFunc = &Mammal::Speak; break;
default: pFunc = &Mammal::Move; break;

Die Zuweisung einer Adresse zu einem Zeiger auf eine Klassenmethode ohne Adressoperator ist nicht standard-konform, wird aber von einigen (vielen?) Compilern unterstützt. Es gibt sogar Compiler (egcs), die pFunc = ptr->Speak; akzeptieren; das geht aber nicht mit virtuellen Methoden.

Übrigens sollte auch ein using namespace std; dazu.
So ist das halt beim "Markt&Technik"-Verlag... :hamma: :motz:
 
Zuletzt bearbeitet:
Oops!!! :eek:
Ich sollte wohl besser beim reinen K&R-C bleiben...
 
Zuletzt bearbeitet:
Besten Dank!

Super, mit dem Adressoperator funktioniert das Ding! Beim Buch ist eine Testversion von MS Visual C++ dabei, damit hätte es vermutlich auch ohne Adressoperator funktioniert. Nö nö, diesen Mircroschrott greif ich nicht an, bleib bei xcode und programmiere standard-konform, wie es auch sein soll!

Danke der_Kay und natürlich auch allen anderen!
 
mdaniela schrieb:
Super, mit dem Adressoperator funktioniert das Ding! Beim Buch ist eine Testversion von MS Visual C++ dabei, damit hätte es vermutlich auch ohne Adressoperator funktioniert. Nö nö, diesen Mircroschrott greif ich nicht an, bleib bei xcode und programmiere standard-konform, wie es auch sein soll!

Danke der_Kay und natürlich auch allen anderen!

gcc's g++ schluckt auch ein paar Sachen die nicht 100% konform sind :D
 
mdaniela schrieb:
...Nö nö, diesen Mircroschrott greif ich nicht an, bleib bei xcode und programmiere standard-konform, wie es auch sein soll!
Ich will Dich nicht irgendwie enttäuschen oder demotivieren, aber in punkto Entwicklungsumgebungen für C/C++ hat Microsoft unangefochten die Nase vorn.
 
Zuletzt bearbeitet:
der_Kay schrieb:
Ich will Dich nicht irgendwie enttäuschen oder demotivieren, aber in punkto Entwicklungsumgebungen für C/C++ hat Microsoft unangefochten die Nase vorn.
und zwar -zugegebenermassen- mit Recht
 
Zurück
Oben Unten