Suche Aufgaben/Tutorials zum Objektlebenszyklus, Vererbung...
-
Guten Morgen,
ich bin dabei meine C++ Kenntnisse wieder aufzufrischen und möchte das gerne weiter praktisch trainieren.
zum Objektlebenszyklus und der Vererbung hätte ich am liebsten Aufgaben die etwas komplizierter sind. So in der Art: 4-5 Klassen mit Vererbung (virtual, dynamischer Speicher usw.) an denen man den Ablauf des Programms feststellen soll.
Also wann der Konstruktor von Class A, B, C, D aufgerufen wird, was ausgeführt wird und wann der Destruktor folgt.
Halt mehrere Verschachtelungen im main Programm.Kann da jemand vielleicht mit ein paar Aufgaben bzw. Links weiterhelfen?
Ich danke schonmal!!
cu
Sven
-
kann mir keiner was anbieten?

-
In Tutorials findet man solche komplexen Sachen selten. Aber wir können uns ja selbst hier etwas zusammenbauen. Dir geht es ja offensichtlich darum, zu sehen, wie OOP so läuft mit möglichst vielen Features.
Hier zunächst mal ein kleines Konstrukt zum Ausbauen:
#include <iostream> #include <conio.h> using namespace std; class C { public: C(){cout<<"ctor C "<<this<<endl;} ~C(){cout<<"dtor C"<<endl;} }; class E { public: E(){cout<<"ctor E "<<this<<endl;} ~E(){cout<<"dtor E"<<endl;} }; class D : public E { public: D(){cout<<"ctor D "<<this<<endl;} ~D(){cout<<"dtor D"<<endl;} }; class A { public: A(){cout<<"ctor A "<<this<<endl;} ~A(){cout<<"dtor A"<<endl;} }; class B : public A { public: B() { cout<<"ctor B "<<this<<endl; pd_ = new D; cout<<pd_<<endl; } ~B() { cout<<"dtor B"<<endl; delete pd_; } private: C c_; D* pd_; }; int main() { { B b; getch(); } getch(); }Ich gebe Dir aus einem meiner eigenen Beispiele hier mal eine Einstiegsversion, den Du ausbauen kannst:
#include <iostream> #include <fstream> #include <string> #include <cctype> #include <conio.h> using namespace std; class Person { public: Person( const string & name = "", const string & info = "" ); //Konstruktor Person( const Person & ); //Copy-Konstruktor Person & operator=( const Person & ); //Zuweisung string getName() const; //liefert Namen zurueck string getInfo() const; //liefert Info zurueck void setName(string s); void setInfo(string s); int operator%( const Person & a ) const; //Aehnlichkeit friend ostream & operator<<( ostream & s, const Person & x ); //Ausgabe private: string name_; // Name der Person string info_; // Information }; /***************** Implementierung ***************************************/ Person::Person( const string & name, const string & info ) : name_(name), info_(info){} Person::Person( const Person & p ) : name_(p.name_), info_(p.info_){} string Person::getName() const { return name_; } string Person::getInfo() const { return info_; } void Person::setName(string s) { name_ = s; } void Person::setInfo(string s) { info_ = s; } Person & Person::operator=( const Person & p ) { name_ = p.name_; info_ = p.info_; return *this; } int Person::operator%( const Person & p ) const // Aehnlichkeit { int gleicheZeichen = 0; // Anzahl gleicher Zeichen int min, max; // kleinste, groesste Laenge if( name_.length() > p.name_.length() ) { max = name_.length(); min = p.name_.length(); } else { min = name_.length(); max = p.name_.length(); } for( int i=0; i < min; ++i ) { if ( toupper( name_[i] ) == toupper( p.name_[i] ) ) ++gleicheZeichen; } return gleicheZeichen; } ostream & operator<<( ostream & out, const Person & p ) { return ( out << p.name_ << '\t' << p.info_ ); } /*************************************************************************/ class Notizbuch { public: Notizbuch(); // Die großen Drei: dtor, copycon, op= // wichtig wegen Zeigervariable ~Notizbuch(); Notizbuch( const Notizbuch & ); Notizbuch & operator=( const Notizbuch & ); void neuerEintrag( const Person & p ); // traegt die Person p ein string getInfo( const string & Name ) const; // liefert Name und Info int getAnzahl() const; friend ostream & operator<<( ostream &, const Notizbuch & ); private: int anzahl_; // Anzahl Eintraege int maxanzahl_; // maximale Anzahl Eintraege Person * pPerson_; // Personen }; /***************** Implementierung ***************************************/ Notizbuch::Notizbuch () : anzahl_(0), maxanzahl_(100) { pPerson_ = new Person[maxanzahl_]; if( !pPerson_ ) maxanzahl_ = 0; } Notizbuch::~Notizbuch() { delete[] pPerson_; }; void Notizbuch::neuerEintrag( const Person & person ) { if( anzahl_ < maxanzahl_ ) { pPerson_[anzahl_] = person; ++anzahl_; } } string Notizbuch::getInfo( const string & Name ) const { if( anzahl_ > 0 ) { Person p = Name; int maxmatch = p % pPerson_[0]; // max. Aehnlichkeit int similarindex = 0; // Index des aehnlichsten for( int i=anzahl_-1; i>0; --i ) { int match = ( p % pPerson_[i] ); // aktuelle Aehnlichkeit if( match >= maxmatch ) // der neueste wird bevorzugt { maxmatch = match; similarindex = i; } } if( maxmatch > 0 ) { return pPerson_[similarindex].getName() + ", " + pPerson_[similarindex].getInfo(); } } else { cout << "Noch keine Eintraege in diesem Notizbuch vorhanden." << endl; } return (""); } int Notizbuch::getAnzahl() const { return anzahl_; } ostream & operator << ( ostream & out, const Notizbuch & nb ) { out << "Gesamtzahl der Eintraege im Notizbuch: " << nb.getAnzahl() << endl << endl; return out; } /*******************************************/ unsigned countData(const string FN) { ifstream in( FN.c_str() ); if(!in) { cerr << "Datei kann nicht geoeffnet werden." << endl; return 0; } else { // Zahl der Eintraege ermitteln int count = 0; for( string s; getline(in, s); ++count ){} return count; } } void loadData( Person * pPerson, const string FN, unsigned count ) { struct data { string name; string info; }; ifstream in( FN.c_str() ); if(!in) { cerr << "Datei kann nicht geoeffnet werden." << endl; } else { data * pData = new data[count]; in.clear(); // EOF-Status loeschen in.seekg(0); // Lesezeiger auf Dateianfang setzen count = 0; for( string s; getline(in, s); ++count ) { int dest = s.find("#",0); pData[count].name = s.substr(0,dest); pData[count].info = s.substr(dest+1); } in.close(); for( int i=0; i<count; ++i ) { pPerson[i].setName(pData[i].name); pPerson[i].setInfo(pData[i].info); } // dynamisches Array auf dem heap freigeben delete[] pData; pData = 0; } } int main() { const string FN = "notizbuch.txt"; unsigned zahl = countData(FN); Person * pP = new Person[zahl]; Notizbuch cpp_teilnehmer; loadData( pP, FN, zahl ); for( int i=0; i<zahl; ++i ) cpp_teilnehmer.neuerEintrag( pP[i] ); cout << cpp_teilnehmer; string suchbegriff; cout << "Bitte Suchbegriff eingeben: " << endl; while( cin >> suchbegriff ) { if( suchbegriff == "#" ) // Programmabbruch durch '#' break; cout << cpp_teilnehmer.getInfo( suchbegriff ) << endl; } delete[] pP; }Dateiaufbau notizbuch.txt im gleichen Verzeichnis wie exe:
Moser Hans#001-464-7373773 Mueller Peter#001-464-3849787
-
Zur Übung der STL:
http://forum.finalfantasy.de/archive/28993/thread.html
http://www.matheboard.de/archiv/thread,1577,gruene-augen-geloest-.htm
http://www.melchisedech.net/Logikratsel/Monche/Losung/losung.html#include <set> #include <iostream> #include <conio.h> using namespace std; class moench; set<moench*> alleMoenche; set<moench*>::iterator pos; set<moench*>::iterator pos1; class moench { private: bool gesund_; bool lebendig_; bool kill_; unsigned anzahl_kranke_Moenche_gesehen_; unsigned anzahl_tage_noch_abwarten_; public: moench(){alleMoenche.insert(this); kill_ = false; lebendig_= true; gesund_ = true; anzahl_kranke_Moenche_gesehen_=0; anzahl_tage_noch_abwarten_=0; } ~moench(){alleMoenche.erase(this);} bool is_lebendig() const {return lebendig_;} bool is_gesund() const {return gesund_;} unsigned wieviele_andere_Moenche_krank() const; // Funktion nachstehend void set_gesund(bool val) {gesund_=val;} void set_anzahl_Tage_noch_abwarten(unsigned val) {anzahl_tage_noch_abwarten_= val;} unsigned get_anzahl_Tage_noch_abwarten() const {return anzahl_tage_noch_abwarten_;} void set_selfkill() {kill_= true;} bool get_selfkill() const {return kill_;} void sich_umbringen() {lebendig_= false;} }; unsigned moench::wieviele_andere_Moenche_krank() const { unsigned count = 0; for( pos1 = alleMoenche.begin(); pos1 != alleMoenche.end(); ++pos1) { if( ( (*pos1)->is_lebendig() == true ) && ( (*pos1) != this ) ) { if( (*pos1)->is_gesund() != true ) count++; } } return count; } int main() { // Moenche /////////////// moench M[10]; M[6].set_gesund(false); M[7].set_gesund(false); M[8].set_gesund(false); M[9].set_gesund(false); ////////////////////////// bool krankheit_besiegt = false; unsigned tag = 0; while( krankheit_besiegt == false ) { // Tag anzeigen tag++; cout << "\nTag: " << tag << endl; for( pos = alleMoenche.begin(); pos != alleMoenche.end(); ++pos) { cout << *pos << " sieht Kranke: " << (*pos)->wieviele_andere_Moenche_krank() << endl; if ( tag == 1 ) { if( (*pos)->wieviele_andere_Moenche_krank() == 0 ) (*pos)->set_selfkill(); else (*pos)->set_anzahl_Tage_noch_abwarten( (*pos)->wieviele_andere_Moenche_krank() ); } else { (*pos)->set_anzahl_Tage_noch_abwarten( (*pos)->get_anzahl_Tage_noch_abwarten() - 1 ); if( (*pos)->get_anzahl_Tage_noch_abwarten() == 0 ) if ( (*pos)->wieviele_andere_Moenche_krank() != 0 ) (*pos)->set_selfkill(); } } // Die Nacht der Entscheidung for( pos = alleMoenche.begin(); pos != alleMoenche.end(); ++pos) { if( (*pos)->get_selfkill() ) (*pos)->sich_umbringen(); } // Test, ob Krankheit besiegt krankheit_besiegt = true; for( pos = alleMoenche.begin(); pos != alleMoenche.end(); ++pos) { if( !(*pos)->is_gesund() && (*pos)->is_lebendig() ) krankheit_besiegt = false; } // Report for( pos = alleMoenche.begin(); pos != alleMoenche.end(); ++pos) { cout << *pos << ": " << "gesund = " << (*pos)->is_gesund() << " lebendig = " << (*pos)->is_lebendig() << " Tage warten: " << (*pos)->get_anzahl_Tage_noch_abwarten() << endl; } getch(); } cout << "\nKrankheit besiegt!" << endl; getch(); }
-
Jetzt noch was mit Templates zum Ausbauen:
#include <iostream> #include <conio.h> using namespace std; template <typename T> void eingabe( T& x ) { cout << "Input: "; cin >> x; } template <typename T> void ausgabe ( const T x ) { cout << "Output: "; cout << x; } int isSchaltjahr( int jahr ) { return !(jahr%4) && jahr%100 || !(jahr%400); } int main() { int jahr; eingabe( jahr ); ausgabe( isSchaltjahr(jahr) ? "ja" : "nein" ); getch(); }#include <iostream> #include <conio.h> template<class T> class Wert { private: T wert_; public: Wert( const T& w ) : wert_(w){}; operator T&(){ return wert_; } }; int main() { Wert<float> f(9.81f); Wert<double> d(19.5); std::cout << d*f; getch(); }#include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> #include <conio.h> class Random_aus_Stdlib_geklaut { private: unsigned seed_; int random() { // so funktioniert rand(): return ((( seed_ = seed_ * 214013L + 2531011L ) >> 16 ) & 0x7fff ); } public: Random_aus_Stdlib_geklaut(){ seed_ = static_cast<unsigned>(time(NULL)); } Random_aus_Stdlib_geklaut( unsigned seed ) { seed_ = seed; } int getNum(){ return random(); } }; class RandomStdlib // verwendet rand() { private: const unsigned int seed_; public: RandomStdlib():seed_( static_cast<unsigned>(time(NULL)) ){} int getNum() const { static bool seed_flag = 0; if( !seed_flag ) { srand( seed_ ); seed_flag = true; } return rand(); } }; class RandomTestEqual // Test auf Gleichverteilung { private: int num_; public: RandomTestEqual() : num_(RAND_MAX - 1){}; int getNum() { ++num_; if( num_ >= RAND_MAX ) num_ = 0; return num_; } }; template< class T_Generator > // Template-Klasse !!! class Wuerfel { private: const unsigned maxzahl_; const unsigned maxrandom_; T_Generator zahlengenerator_; // Template-Typ als Attribut public: Wuerfel( unsigned maxzahl ) : maxzahl_(maxzahl), maxrandom_(RAND_MAX-(RAND_MAX%maxzahl)) {} unsigned wuerfelt() { unsigned r; do{ r = zahlengenerator_.getNum(); } while ( r >= maxrandom_ ); return ( r % maxzahl_ + 1 ); } }; int main() { const unsigned long long Serie = 3; const unsigned long long Versuche = 30000000; const unsigned limit = 200; const unsigned moeglichkeiten = 6; Wuerfel<RandomTestEqual> w0a( moeglichkeiten ); Wuerfel<RandomTestEqual> w0b( 2 ); Wuerfel<RandomStdlib> w1a( moeglichkeiten ); Wuerfel<RandomStdlib> w1b( 2 ); Wuerfel<Random_aus_Stdlib_geklaut> w2a( moeglichkeiten ); Wuerfel<Random_aus_Stdlib_geklaut> w2b( 2 ); unsigned long long H[moeglichkeiten+1]; for( unsigned long long i=1; i<Serie+1; ++i ) { for( unsigned j=0; j<moeglichkeiten+1; ++j ) H[j] = 0; for( unsigned long long k=1; k<Versuche+1; ++k ) { unsigned wurf = w1a.wuerfelt(); // hier wird gewürfelt !!!! if( Versuche<limit ) std::cout << wurf << " "; ++H[wurf]; } for( unsigned c=1; c<moeglichkeiten+1; ++c ) { std::cout << std::endl << c << ": " << H[c] << " " << std::setprecision(7) << 100 * static_cast<float>(H[c]) / Versuche << " %"; H[0] += H[c]; } std::cout << std::endl << "Wuerfe insgesamt: " << H[0] << std::endl << std::endl; } getch(); }
-
Noch was Virtuelles:
#include <iostream> #include <conio.h> using namespace std; class Teilnehmer { private: string name_; char sex_; public: string getName() const { return name_; } char getSex() const { return sex_; } Teilnehmer(){} Teilnehmer(string name, char sex) : name_(name), sex_(sex) {} virtual //kommentiere dies mal aus void take_the_Floor() { cout << "Teilnehmer " << getName() << " erhaelt Floor" << endl; } }; class Dozent : public Teilnehmer { public: Dozent(string name, char sex) : Teilnehmer(name,sex){}; void take_the_Floor() { string s; if( getSex() == 'm' ) s = "Dozent "; else s = "Dozentin "; cout << s << getName() << " erhaelt Floor " << "und erlaeutert Details des Stoffes." << endl; } }; class Schueler : public Teilnehmer { public: Schueler(string name, char sex) : Teilnehmer(name,sex){}; void take_the_Floor() { string s; if( getSex() == 'm' ) s = "Schueler "; else s = "Schuelerin "; cout << s << getName() << " erhaelt Floor " << "und stellt Fragen zum Unterrichtsstoff." << endl; } }; void trauDich(Teilnehmer * tn) { tn->take_the_Floor(); } int main() { Schueler t1("Hagen", 'm'); Schueler t2("Ilonka",'w'); Dozent t3("Peter",'m'); Dozent t4("Ms X", 'w'); Teilnehmer * pT[3]; pT[0] = &t1; pT[1] = &t2; pT[2] = &t3; pT[3] = &t4; for( int i=0; i<4; ++i ) trauDich( pT[i] ); /* Bedingt durch frühe Bindung legt der Compiler die Verbindung zur Elementfunktion beim Übersetzen fest. Es wäre aber wünschenswert, dass ein übergebenes Objekt selbst prüft, welche Member-Funktion zu ihm gehört. Es kann jedoch erst zur Laufzeit des Programms getestet werden, welches Objekt sich hinter dem Zeiger befindet. */ getch(); }#include <iostream> #include <conio.h> using namespace std; class Person { public: virtual // versuchsweise auskommentieren void geldueberweisung(float geld){ cout << geld << " an Person " << endl; }; }; class Mitarbeiter : public Person { public: void geldueberweisung(float geld){ cout << geld << " an Mitarbeiter " << endl; }; }; class Kunde : public Person { public: void geldueberweisung(float geld){ cout << geld << " an Kunde " << endl; }; }; class Lieferant : public Person { public: void geldueberweisung(float geld){ cout << geld << " an Lieferant " << endl;}; }; void zahlung(Person * x, float Summe) { x->geldueberweisung(Summe); } int main() { Lieferant a; Kunde b; Mitarbeiter c,d; zahlung( &a, 500 ); zahlung( &b, 300 ); zahlung( &c, 250 ); zahlung( &d, 170 ); getch(); }
-
Fehlt Dir noch etwas?
Exceptions sollte man auch verstehen/üben:
#include <conio.h> #include <iostream> int main() { class irgendwas { public: void print() { std::cerr << "catch as catch can." << std::endl; } }; try { throw irgendwas(); } catch(irgendwas& e) { e.print(); } getch(); }... und hier noch eine Testklasse zum Container testen:
////////////////////////////////////// //Xint_Sonde.h ////////////////////////////////////// #define _TEST_ #include <windows.h> #include <conio.h> #include <iostream> /* 0 BLACK, 1 BLUE, 2 GREEN, 3 CYAN, 4 RED, 5 MAGENTA, 6 BROWN, 7 LIGHTGRAY, 8 DARKGRAY, 9 LIGHTBLUE, 10 LIGHTGREEN, 11 LIGHTCYAN, 12 LIGHTRED, 13 LIGHTMAGENTA, 14 YELLOW, 15 WHITE */ void textcolor(WORD color) { SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), color); } const int farbe1 = 3; const int farbe2 = 15; class Xint { private: int num; static int countCtor; static int countDtor; static int countCopycon; static int countOpAssign; public: Xint() { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "ctor" << std::endl; textcolor(farbe2); #endif ++countCtor; } ~Xint() { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "dtor" << std::endl; textcolor(farbe2); #endif ++countDtor; } Xint(const Xint& x) { #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "copycon von " << std::dec << &x << std::endl; textcolor(farbe2); #endif num = x.getNum(); ++countCopycon; } Xint& operator=(const Xint& x) { if (&x == this) { #ifdef _TEST_ textcolor(farbe1); std::cout << "Selbstzuweisung mit op=" << std::endl; textcolor(farbe2); #endif } #ifdef _TEST_ textcolor(farbe1); std::cout << this << ": " << "op= von " << std::dec << &x << std::endl; textcolor(farbe2); #endif num = x.getNum(); ++countOpAssign; return *this; } int getNum() const {return num;} void setNum(int val) {num = val;} static void statistik(std::ostream&); static void reset(); }; int Xint::countCtor = 0; int Xint::countDtor = 0; int Xint::countCopycon = 0; int Xint::countOpAssign = 0; void Xint::statistik(std::ostream& os) { textcolor(farbe1); os << "Ctor: " << countCtor << std::endl << "Dtor: " << countDtor << std::endl << "Copycon: " << countCopycon << std::endl << "op=: " << countOpAssign; textcolor(farbe2); } void Xint::reset() { countCtor = 0; countDtor = 0; countCopycon = 0; countOpAssign = 0; } std::ostream& operator<< (std::ostream& os, const Xint& x) { os << x.getNum(); return os; } bool operator< (const Xint& a, const Xint& b) { return a.getNum() < b.getNum(); } bool operator> (const Xint& a, const Xint& b) { return a.getNum() > b.getNum(); } bool operator== (const Xint& a, const Xint& b) { return a.getNum() == b.getNum(); } bool operator!= (const Xint& a, const Xint& b) { return a.getNum() != b.getNum(); } ////////////////////////////////////// //Xint_Sonde.cpp ////////////////////////////////////// #include <deque> #include <vector> #include <list> #include <algorithm> #include <iostream> #include <conio.h> #include "Xint_Sonde.h" using namespace std; int main () { cout << "Container-Typ: " << "vector" << endl; vector<Xint> ct; // Hier Containertyp tauschen vector<Xint>::iterator it; // ... und hier den Iterator anpassen const int N = 3; Xint x; cout << endl << N << " mal push_back (hinten anhaengen)." << endl; for(size_t i=0; i<N; ++i) { x.setNum(i); ct.push_back(x); } cout << endl; for(it=ct.begin();it!=ct.end();++it) { cout << *it << endl; } cout << endl; Xint::statistik(cout); Xint::reset(); cout << endl << endl; cout << "Zahl 42 am Anfang einschieben." << endl; x.setNum(42); it = ct.begin(); ct.insert(it,x); cout << endl; for(it=ct.begin();it!=ct.end();++it) { cout << *it << endl; } cout << endl; Xint::statistik(cout); Xint::reset(); cout << endl << endl; cout << "Sortieren." << endl; sort(ct.begin(),ct.end()); //ct.sort(); cout << endl; for(it=ct.begin();it!=ct.end();++it) { cout << *it << endl; } cout << endl; Xint::statistik(cout); Xint::reset(); cout << endl << endl; getch(); }Wenn Du in OOP richtig fit werden willst, solltest Du bei Herb Sutters Guru of the Week vorbei schauen:
http://www.gotw.ca/gotw/
-
Vielen Dank Erhard für die ganzen Beispiele und Infos!!!
da weiß ich schon was ich das ganze Wochenende über zu tun habe

ich meld mich dann wieder mit meinen vielen Fragen
cu
sven