Virtuelle Funktionen: Problem mit Programm aus Übungsbuch
-
Hallo zusammen,
ich habe das Buch "C++ IT-Tutorial" von Herbert Schildt. Hab nun ein Problem mit einem Programm.
Hier erst mal der Code:
// p10-16.cpp // Mit virtuellen Funktionen und Polymorphie arbeiten. #include <iostream> #include <cstring> using namespace std; // Eine Klasse fuer zweidimensionale Objekte. class TwoDShape { // Diese Elemente sind privat. double width; double height; // Ein Namensfeld hinzufuegen. char name[20]; public: // Standardkonstruktor TwoDShape() { width = height = 0.0; strcpy(name, "unbekannt"); } // Konstruktor fuer TwoDShape TwoDShape(double w, double h, char *n) { width = w; height = h; strcpy(name, n); } // Ein Objekt mit gleicher Breite und Hoehe konstruieren. TwoDShape(double x, char *n) { width = height = x; strcpy(name, n); } void showDim() { cout << "Breite und Hoehe sind " << width << " und " << height << ".\n"; } // Zugriffsfunktionen double getWidth() { return width; } double getHeight() { return height; } void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } char *getName() { return name; } // Die virtuelle Funktion area() zu TwoDShape hinzufuegen. virtual double area() { cout << "Fehler: area() muss ueberschrieben werden.\n"; return 0.0; } }; // Triangle ist von TwoDShape abgeleitet. class Triangle : public TwoDShape { char style[20]; // jetzt privat public: /* Ein Standardkonstruktor. Er ruft automatisch den Standardkonstruktor von TwoDShape auf. */ Triangle() { strcpy(style, "unbekannt"); } // Konstruktor mit drei Parametern. Triangle(char *str, double w, double h) : TwoDShape(w, h, "dreieckig") { strcpy(style, str); } // Ein gleichschenkliges Dreieck konstruieren. Triangle(double x) : TwoDShape(x, "gleichschenklig") { strcpy(style, "gleichschenklig"); } // Dies ueberschreibt jetzt area() in TwoDShape. double area() { return getWidth() * getHeight() / 2; } void showStyle() { cout << "Das Dreieck ist "<< style << ".\n"; } }; // Eine abgeleitete Klasse von TwoDShape fuer Rechtecke. class Rectangle : public TwoDShape { public: // Ein Rechteck konstruieren. Rectangle(double w, double h) : TwoDShape(w, h, "rechteckig") { } // Ein Quadrat konstruieren. Rectangle(double x) : TwoDShape(x, "quadratisch") { } bool isSquare() { if(getWidth() == getHeight()) return true; return false; } // Auch hier wird area() ueberschrieben. double area() { return getWidth() * getHeight(); } }; int main() { // Ein Array von Zeigern auf TwoDShape-Objekte deklarieren. TwoDShape *shapes[5]; shapes[0] = &Triangle("rechtwinklig", 8.0, 12.0); shapes[1] = &Rectangle(10); shapes[2] = &Rectangle(10, 4); shapes[3] = &Triangle(7.0); shapes[4] = &TwoDShape(10, 20, "generisch"); for(int i=0; i < 5; i++) { cout << "Das Objekt ist " << shapes[i]->getName() << ".\n"; cout << "Die Flaeche ist " << shapes[i]->area() << ".\n"; cout << "\n"; } return 0; }So laut Buch sollte dieses Programm folgenden Output erzeugen:
Das Objekt ist dreieckig. Die Flaeche ist 48. Das Objekt ist quadratisch. Die Flaeche ist 100. Das Objekt ist rechteckig. Die Flaeche ist 40. Das Objekt ist gleichschenklig. Die Flaeche ist 24.5. Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0.Bei mir wird aber Folgendes ausgegeben:
Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0. Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0. Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0. Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0. Das Objekt ist generisch. Fehler: area() muss ueberschrieben werden. Die Flaeche ist 0.Hab das Programm mit zwei verschiedenen Compilern erstellt, mit dem von Dev-C++ und mit dem von Visual C++ 2005 Express Edition, bei beiden das selbe Ergebnis.
Dev-C++ bringt auch folgende Warnungen:
116 16.cpp warning: taking address of temporary 117 16.cpp warning: taking address of temporary 118 16.cpp warning: taking address of temporary 119 16.cpp warning: taking address of temporary 120 16.cpp warning: taking address of temporaryIch hoffe mir kann jemand sagen warum das Programm nicht so funktioniert wie im Buch beschrieben. Und mir folgenden Abschnitt mal ein bisschen genauer erklären, steh da noch ein wenig auf der Leitung.
shapes[0] = &Triangle("rechtwinklig", 8.0, 12.0); shapes[1] = &Rectangle(10); shapes[2] = &Rectangle(10, 4); shapes[3] = &Triangle(7.0); shapes[4] = &TwoDShape(10, 20, "generisch");Ich wünsch euch noch einen schönen Sonntag.
MfG
Christian
-
Kagerer schrieb:
shapes[0] = &Triangle("rechtwinklig", 8.0, 12.0); shapes[1] = &Rectangle(10); shapes[2] = &Rectangle(10, 4); shapes[3] = &Triangle(7.0); shapes[4] = &TwoDShape(10, 20, "generisch");Wenn dies wirklich so im Buch steht, wirf es bitte weg, denn das ist einfach nur falsch.
Mit Triangle("rechtwinklig", 8.0, 12.0) erzeugst Du ein temporäres Objekt vom Typ Triangle. Davon holst Du dir mit & die Adresse. Danach wird das temporäre Objekt zerstört. Die Adresse ist also ungültig. Alles weitere was mit shapes[0] passiert ist schon undefiniert.
So müsste es aussehen:
shapes[0] = new Triangle(.....);Aber am Ende nicht vergessen:
delete shapes[0];
-
Vielen Dank für deine schnelle Antwort.
So funktionierts und ja das steht wirklich so im Buch, hab auch den Qellcode von http://www.mitp.de/vmi/mitp/detail/pWert/0980/titel/C%2B%2B%20IT-Tutorial runtergeladen, steht da aber genauso.
Die Operatoren new und delete kenne ich noch gar nicht, die kommen erst im übernächsten Kapitel.

Gruß
Christian
-
So im nächsten Beispiel steht praktisch wieder derselbe Blödsinn.
int main() { // Ein Array von Zeigern auf TwoDShape-Objekte deklarieren. TwoDShape *shapes[4]; shapes[0] = &Triangle("rechtwinklig", 8.0, 12.0); shapes[1] = &Rectangle(10); shapes[2] = &Rectangle(10, 4); shapes[3] = &Triangle(7.0); for(int i=0; i < 4; i++) { cout << "Das Objekt ist " << shapes[i]->getName() << ".\n"; cout << "Die Flaeche ist " << shapes[i]->area() << ".\n"; cout << "\n"; } return 0; }Gut das ich jetzt weiß wie es richtig geht.

-
Warum nimmste nicht gleich ein anderes C++ Buch, wenn dieses derart Fehler enthält?
Es gibt doch viele, gute andere Bücher noch.Auf der Hauptseite hat es daher viele Buchempfehlungen. Schau dir das evtl. mal an.

-
Werd die letzten beiden Kapitel im Buch auch noch durchgehen. Waren ja die ersten groben fehler die mir aufgefallen sind. Hoffe gibt nicht noch mehr davon.

MfG
Christian
-
Kagerer schrieb:
shapes[0] = &Triangle("rechtwinklig", 8.0, 12.0); shapes[1] = &Rectangle(10); shapes[2] = &Rectangle(10, 4); shapes[3] = &Triangle(7.0); shapes[4] = &TwoDShape(10, 20, "generisch");an sich dürfte das nicht einmal compilieren, da der operator & ein lvalue verlangt und kein memberoperator & definiert wurde. aber bei solchen feinheiten haben einige compiler schwierigkeiten.
-
Also wie gesagt Dev-C++ und Visual C++ 2005 kompilieren es.
Dev-C++ bringt folgende Warnungen:
116 16.cpp warning: taking address of temporary
117 16.cpp warning: taking address of temporary
118 16.cpp warning: taking address of temporary
119 16.cpp warning: taking address of temporary
120 16.cpp warning: taking address of temporaryVisual C++ bringt nur 6x die Meldung das 'strcpy' veraltet ist und ich 'strcpy_s' verwenden soll.
Gruß
Christian
-
stell ich visual c++ 2005 die spracherweiterungen ab, weist er das ganze korrekt zurück mit:
(116) : error C2102: '&' requires l-valuemit language-extensions on (dummerweise der standard, aber notwendig für windows header u.ä.), gibt es eine level 4 warnung
(116) : warning C4238: nonstandard extension used : class rvalue used as lvalueg++ hab ich gerade nicht zur hand, ich stell mir aber vor, dass da mit -pedantic oder -ansi etwas weniger harmloses als die erwähnte warnung geschiueht.