/************************************************ * Programm: Classdemo 1 * * Autor: Gerhard Zapf tutorialpage.de * * Beschreibung: Demo der Polymorphie * ***********************************************/ #include #include // Legt Grenzen für Variableninhalte fest #include // Für strcpy und strlen /* Erstmal PI festlegen */ const double PI = 3.141592653; /*********************************** *** Beschreibung der Klasse CForm ***********************************/ class CForm { public: /* Der Destruktor zum Aufräumen des Speichers */ ~CForm() { delete [] name_z; }; /* Ausgeben der Klassendaten */ virtual void schreib(); private: /* Der Name der Form (Benutzereingabe) */ char* name_z; const static char wortlaenge; protected: /*************************************************************************** * Diese Funktion wird hier nur bekanntgemacht. Alle abgeleiteten Klassen * * MÜSSEN sie ebenfalls definieren. Das =0 legt fest, dass diese Funktion * * hier nur definiert, nicht deklariert wird. Das VIRTUAL legt fest, dass * * Ableitungen von CForm eigene Versionen der Klasse verwenden sollen * **************************************************************************/ virtual double flaeche() = 0; /* Eigener Operator für die = Funktion * protecetd deshalb, dass er nicht auf abgeleitete Klassen * angewendet wird, die ihn nicht definieren (z.B. CKreis!) */ CForm& operator=( const CForm& ); /* Der Standart-Konstruktor */ CForm(); /* Kopierkonstruktor */ CForm( const CForm&); }; /* Initialisierung der Konstanten aus CForm */ const char CForm::wortlaenge = 20; CForm::CForm() // Default-Konstruktor { /* Zwischenspeicher für Eingabe */ char puffer[wortlaenge]; /* Den Namen einlesen */ cout << "Name der Form: "; cin.get(puffer, wortlaenge); cin.ignore(INT_MAX, '\n'); /* Und aus dem Puffer in das Objekt kopieren */ name_z = new char[strlen(puffer) +1 ]; strcpy( name_z, puffer ); } /* Der Kopierkonstruktor von CForm */ CForm::CForm( const CForm& quelle) { name_z = new char[strlen(quelle.name_z) +1]; strcpy( name_z, quelle.name_z ); } /* Hier wird eine eigene Version des Operators = definiert */ CForm& CForm::operator=( const CForm& quelle ) { /* Wenn das Zielobjekt nicht leer ist, muss der alte Name zuerst gelöscht werden um Speicherlecks zu vermeiden */ if( name_z != 0 ) { delete [] name_z; } name_z = new char[ strlen(quelle.name_z) +1 ]; strcpy( name_z, quelle.name_z ); return *this; } void CForm::schreib() { cout << "Name der Form: " << name_z << endl; } /*********************************** *** Beschreibung der Klasse CKreis ***********************************/ // Abgeleitet von CForm // Alle Elemente behalten durch die public-Ableitung // Ihren Zugriffsschutz-Status bei class CKreis : public CForm { public: CKreis(); CKreis( const CKreis& ); // Kopier-Konstruktor void schreib(); private: /* Berechnung der Kreisflaeche */ // Weglassen der Funktion löst fehler beim Linken des Codes aus weil // flaeche in CForm virtual ist! double flaeche(); // Die Funktion gilt jetzt als überladen! double m_dRadius; // Kreisradius }; CKreis::CKreis() { // Der Konstruktor von CForm wird automatisch vorher aufgerufen! cout << "Kreisradius: "; cin >> m_dRadius; cin.ignore(INT_MAX, '\n'); } /* Noch bevor in den Anweisungsteil von CKreis verzweigt wird, muss * der Kopierkonstruktor von CForm aufgerufen werden, damit nicht * fälschlicherweise der Standartkonstruktor von CForm gerufen wird */ CKreis::CKreis( const CKreis& quelle ) : CForm(quelle) { m_dRadius = quelle.m_dRadius; } void CKreis::schreib() { /***************************************************************************** * Das Einführen der Variable Fläche führt zu einem Namenskonflikt, weil die * * Klasse CKreis bereits eine Funktion selben Namens kennt. In der Funktion * * schreib() wird flaeche() von double flaeche überlagert und ist nichtmehr * * implizit erreichbar! Deshalb wird mit dem Zeiger this (der immer auf das * * Objekt zeigt, mit welchem man gerade arbeitet) explizit auf flaeche() zu- * * gegriffen. * ****************************************************************************/ double flaeche = this->flaeche(); /* Zuerst die Funktion schreib() der Basisklasse aufrufen */ CForm::schreib(); cout << "Radius: " << m_dRadius << endl; cout << "Flaeche: " << flaeche << endl; } double CKreis::flaeche() { return PI * m_dRadius * m_dRadius; } /*********************************** *** Beschreibung der Klasse CRechteck ***********************************/ class CRechteck : public CForm { public: CRechteck(); CRechteck( const CRechteck& ); // Kopierkonstruktor void schreib(); /* Überladen des Operators = */ CRechteck& operator=(const CRechteck&); private: double flaeche(); double m_dLaenge; double m_dBreite; }; CRechteck::CRechteck() { cout << "Laenge des Rechtecks: "; cin >> m_dLaenge; cout << "Breite des Rechtecks: "; cin >> m_dBreite; cin.ignore(INT_MAX, '\n'); } CRechteck::CRechteck( const CRechteck& quelle ) : CForm( quelle ) { m_dLaenge = quelle.m_dLaenge; m_dBreite = quelle.m_dBreite; } CRechteck& CRechteck::operator=(const CRechteck& quelle) { /* Zuerst Funktion aus der Basisklasse aufrufen */ CForm::operator=(quelle); m_dLaenge = quelle.m_dLaenge; m_dBreite = quelle.m_dBreite; return *this; } double CRechteck::flaeche() { return m_dLaenge * m_dBreite; } void CRechteck::schreib() { double flaeche = this->flaeche(); CForm::schreib(); cout << "Laenge, Breite: " << m_dLaenge << ", " << m_dBreite << endl; cout << "Flaeche: " << flaeche << endl; } /*** Hauptprogramm ***/ void main() { CKreis test; CRechteck rect1; CForm* feld[2]; feld[0] = &rect1; feld[1] = &test; feld[0]->schreib(); feld[1]->schreib(); }