C++ für Fortgeschrittene |
#include
<limits> #include <iostream> void wait() { //std::cout << "wait: press any key" << std::endl; std::cin.clear(); std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); std::cin.get(); } int main() { std::cout << "hello, world (Brian Kernighan 1974)\nI am a C++ program" << std::endl; wait(); } |
#include
<limits> #include <iostream> #include <string> void wait() { //std::cout << "wait: press any key" << std::endl; std::cin.clear(); std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); std::cin.get(); } int main() { try { throw std::string ("Hallo Welt!"); } catch (std::string& s) { std::cout << s << std::endl; } wait(); } |
|
Kapselung: | Eigenschaften und Verhaltensweisen fasst man gekapselt in einem Objekt zusammen. |
Verbergen von Daten: | Die aus Außensicht wichtigen Funktionen sind zugänglich, alle anderern werden verborgen. |
Vererbung: | Man kann eine Kind-Klasse definieren, die eine Erweiterung einer schon bestehenden Klasse darstellt. |
Polymorphie: | Eine Verhaltensweise kann ihre Wirkungsweise ändern - abhängig von äußeren Ereignissen. |
#define NOMINMAX //
due to conflict with max() #include <limits> #include <windows.h> #include <iostream> #include <utility> // for std::exchange void wait() { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); } void textcolor(WORD color) { SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), color); } constexpr int farbe1 = 11; constexpr int farbe2 = 15; class xINT { private: int num = 0; // initialize with default value static int countCtor; static int countDtor; static int countCopycon; static int countOpAssign; public: xINT() { textcolor(farbe1); std::cout << this << ": " << "ctor" << std::endl; textcolor(farbe2); ++countCtor; } ~xINT() { textcolor(farbe1); std::cout << this << ": " << "dtor" << std::endl; textcolor(farbe2); ++countDtor; } xINT(const xINT& x) : num(x.num) { textcolor(farbe1); std::cout << this << ": " << "copycon von " << std::dec << &x << std::endl; textcolor(farbe2); ++countCopycon; } xINT& operator=(const xINT& x) { if (this != &x) { textcolor(farbe1); std::cout << this << ": " << "op= von " << std::dec << &x << std::endl; textcolor(farbe2); num = x.num; ++countOpAssign; } else { textcolor(farbe1); std::cout << "Selbstzuweisung mit op=" << std::endl; textcolor(farbe2); } 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; } std::istream& operator>>(std::istream& is, xINT& x) { int i; is >> i; x.setNum(i); return is; } 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(); } // Unser Testfeld int main(){ { xINT i; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
...
int main() { xINT *pi; { pi = new xINT; wait(); } wait(); delete pi; wait(); xINT::statistik(std::cout); wait(); } |
... int main() { xINT *pi; { pi = new xINT[5]; wait(); } wait(); delete[] pi; wait(); xINT::statistik(std::cout); wait(); } |
In modernen C++-Programmen wird die Verwendung von new
und delete
weitgehend
als veraltet betrachtet, vor allem wegen der erhöhten Fehleranfälligkeit und der
Notwendigkeit, manuell Speicher zu verwalten. Stattdessen wird die Verwendung
von Smart Pointern (std::unique_ptr
, std::shared_ptr
)
und Containern der Standardbibliothek wie std::vector
empfohlen.
Wenn man dennoch new
und delete
verwendet,
ist es wichtig, zwischen new
und new[]
sowie delete
und delete[]
zu
unterscheiden. Der Operator new[]
wird
verwendet, um ein Array von Objekten zu erstellen, und entsprechend muss delete[]
verwendet
werden, um dieses Array freizugeben. Andernfalls führt dies zu undefiniertem
Verhalten.
... class A : public xINT { private: double a; public: A(){std::cout << this << ": " << "A ctor" << std::endl;} ~A(){std::cout << this << ": " << "A dtor" << std::endl;} }; int main() { { A a; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
... class A { private: double a; xINT i; public: A(){std::cout << this << ": " << "A ctor" << std::endl;} ~A(){std::cout << this << ": " << "A dtor" << std::endl;} }; int main() { { A a; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
... class B { private: int b; public: B(){std::cout << this << ": " << "B ctor" << std::endl;} ~B(){std::cout << this << ": " << "B dtor" << std::endl;} }; class A : public B { private: double a; xINT i1; xINT i2; public: A(){std::cout << this << ": " << "A ctor" << std::endl;} ~A(){std::cout << this << ": " << "A dtor" << std::endl;} }; int main() { { A a; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
... class A : public xINT { private: double a; public: A(){std::cout << this << ": " << "A ctor" << std::endl;} ~A(){std::cout << this << ": " << "A dtor" << std::endl;} }; class B : public xINT { private: double b; public: B(){std::cout << this << ": " << "B ctor" << std::endl;} ~B(){std::cout << this << ": " << "B dtor" << std::endl;} }; class D : public A, public B { private: double d; public: D(){std::cout << this << ": " << "D ctor" << std::endl;} ~D(){std::cout << this << ": " << "D dtor" << std::endl;} }; int main() { { D d; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
int main() { { D d; std::cout << d.getNum() << std::endl; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
int main() { { D d; std::cout << std::endl; std::cout << d.A::getNum() << std::endl; std::cout << d.B::getNum() << std::endl; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
... class A : virtual public xINT { private: double a; public: A(){std::cout << this << ": " << "A ctor" << std::endl;} ~A(){std::cout << this << ": " << "A dtor" << std::endl;} }; class B : virtual public xINT { private: double b; public: B(){std::cout << this << ": " << "B ctor" << std::endl;} ~B(){std::cout << this << ": " << "B dtor" << std::endl;} }; class D : public B, public A { private: double d; public: D(){std::cout << this << ": " << "D ctor" << std::endl;} ~D(){std::cout << this << ": " << "D dtor" << std::endl;} }; int main() { { D d; std::cout << std::endl; std::cout << d.getNum() << std::endl; std::cout << d.A::getNum() << std::endl; std::cout << d.B::getNum() << std::endl; wait(); } wait(); xINT::statistik(std::cout); wait(); } |
... class A { public: A(xINT i){i_=i;} //Zuweisung im Konstruktor private: xINT i_; }; class B { public: B(xINT i):i_(i){} //Initialisierungsliste private: xINT i_; }; int main() { xINT i; i.setNum(42); wait(); { std::cout << "Klasse A:" << std::endl; A a(i); wait(); std::cout << "Klasse B:" << std::endl; B b(i); wait(); } wait(); } |
... #include <vector> #include <list> #include <deque> #include <algorithm> 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 = 1; //verändern 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; wait(); } |
Ausgabe für N=1: | Ausgabe für N=2: |
Container-Typ: vector 0012FF4C: ctor 1 mal push_back (hinten anhaengen). 0012FEE0: copycon von 0012FF4C 00316498: copycon von 0012FEE0 0012FEE0: dtor 0 Ctor: 1 Dtor: 1 Copycon: 2 op=: 0 Zahl 42 am Anfang einschieben. 0012FF08: copycon von 0012FF4C 003164A8: copycon von 0012FF08 003164AC: copycon von 00316498 00316498: dtor 0012FF08: dtor 42 0 Ctor: 0 Dtor: 2 Copycon: 3 op=: 0 Sortieren. 0012FF04: copycon von 003164AC 003164AC: op= von 003164A8 003164A8: op= von 0012FF04 0012FF04: dtor 0 42 Ctor: 0 Dtor: 1 Copycon: 1 op=: 2 |
Container-Typ: vector 0012FF48: ctor 2 mal push_back (hinten anhaengen). 0012FEE0: copycon von 0012FF48 00316498: copycon von 0012FEE0 0012FEE0: dtor 0012FEE0: copycon von 0012FF48 003164A8: copycon von 00316498 003164AC: copycon von 0012FEE0 00316498: dtor 0012FEE0: dtor 0 1 Ctor: 1 Dtor: 3 Copycon: 5 op=: 0 Zahl 42 am Anfang einschieben. 0012FF08: copycon von 0012FF48 003164B8: copycon von 0012FF08 003164BC: copycon von 003164A8 003164C0: copycon von 003164AC 003164A8: dtor 003164AC: dtor 0012FF08: dtor 42 0 1 Ctor: 0 Dtor: 3 Copycon: 4 op=: 0 Sortieren. 0012FF04: copycon von 003164BC 003164BC: op= von 003164B8 003164B8: op= von 0012FF04 0012FF04: dtor 0012FF04: copycon von 003164C0 003164C0: op= von 003164BC 003164BC: op= von 0012FF04 0012FF04: dtor 0 1 42 Ctor: 0 Dtor: 2 Copycon: 2 op=: 4 |
xINT( const
xINT& x
) { num = x.getNum();
} (blau: Original, rot: Kopie) |
//... int main() { cout << "Container-Typ: " << "list" << endl; list<xINT> ct; // Hier Containertyp tauschen list<xINT>::iterator it; // ... und hier den Iterator anpassen const int N = 2; 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(); //für list diese Anweisung verwenden! cout << endl; for(it=ct.begin();it!=ct.end();++it) { cout << *it << endl; } cout << endl; xINT::statistik(cout); xINT::reset(); cout << endl << endl; wait(); } |
Hinten-Anhängen: | Ctor:
1 Dtor: 0 Copycon: 10000000 op=: 0 |
Vorne-Reinschieben | Ctor:
0 Dtor: 0 Copycon: 1 op=: 0 |
Sortieren |
Ctor:
0 Dtor: 0 Copycon: 0 op=: 0 |
cout
<< "Container-Typ: " << "deque" << endl; deque<xINT> ct; // Hier Containertyp tauschen deque<xINT>::iterator it; // ... und hier den Iterator anpassen //... sort(ct.begin(),ct.end()); |
... #include <vector> #include <list> #include <deque> #include <algorithm> using namespace std; int main() { cout << "Container-Typ: " << "vector" << endl; vector<xINT> ct, ct1; // Hier Containertyp tauschen vector<xINT>::iterator it; // ... und hier den Iterator anpassen const int N = 10; 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 << "Container komplett neu zuweisen" << endl; ct1 = ct; cout << endl; xINT::statistik(cout); xINT::reset(); cout << endl << endl; wait(); } |
//... int main() { cout << "Container-Typ: " << "vector" << endl; vector<xINT> ct, ct1; // Hier Containertyp tauschen vector<xINT>::iterator it; // ... und hier den Iterator anpassen const int N = 10; xINT x; ct.reserve(N); //Speicherplatz vorab reservieren für N Elemente 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; //... |
xINT&
operator= ( const xINT& x ) { if (&x == this) { std::cout << "Selbstzuweisung mit op=" << std::endl; } num = x.getNum(); return *this; } (blau: Original, rot: Kopie mit gleichzeitiger Überschreibung eines hoffentlich(!) nicht mehr benötigten Objektes) |
... int main() { { xINT i1, i2; i1.setNum(42); i2 = i1; std::cout << i1.getNum() << " " << i2.getNum() << std::endl; wait(); } wait(); } |
... int main() { { xINT i1; i1.setNum(42); i1 = i1; std::cout << i1.getNum() << std::endl; wait(); } wait(); } |
xINT&
operator=(const xINT& x) { if (&x == this) // Quelle und Ziel identisch ==> Selbstzuweisung!!! { #ifdef _TEST_ //textcolor(farbe1); std::cout << this << ": Achtung! Selbstzuweisung mit op=" << std::endl; //textcolor(farbe2); #endif ++countOpAssign; return *this; //Schutz } #ifdef _TEST_ //textcolor(farbe1); std::cout << this << ": " << "op= von " << std::dec << &x << std::endl; //textcolor(farbe2); #endif num = x.getNum(); ++countOpAssign; return *this; } |
std::ostream& operator<<
(std::ostream& os, const xINT& x) { os << x.getNum(); return os; } std::istream& operator>> (std::istream& is, xINT& x) { int i; is >> i; x.setNum(i); return is; } |
... #include <fstream> #include <vector> #include <algorithm> using namespace std; int main() { { const int N = 10; xINT x; //ctor der Testklasse xINT in Aktion vector<xINT> ct; //Container ct.reserve(N); //Wichtig für die Effizienz! for(int i=0; i<N; ++i) { x.setNum(i); ct.push_back(x); //copycon der Testklasse xINT in Aktion } //Speichervorgang in File fstream file("output.txt", ios::out); if(!file) { cout << "Datei konnte nicht erzeugt/geoeffnet werden" << endl; return 2; //ERROR_FILE_NOT_FOUND } file << ct.size() << " "; //Wichtig für ein späteres ct.reserve(...) beim Lesen copy( ct.begin(), ct.end(), ostream_iterator<xINT>(file," ") ); file.close(); wait(); } //dtor der Testklasse xINT in Aktion xINT::statistik(cout); xINT::reset(); wait(); return 0; } |
... #include <fstream> #include <vector> #include <algorithm> using namespace std; int main() { const int N = 10; xINT x; //ctor der Testklasse xINT in Aktion vector<xINT> ct; //Container ct.reserve(N); //Wichtig für die Effizienz! for(int i=0; i<N; ++i) { x.setNum(i); ct.push_back(x); //copycon der Testklasse xINT in Aktion } cout << "\nSpeichern in File\n" << endl; fstream file("output.txt", ios::out); if(!file) { cout << "Datei konnte nicht erzeugt/geoeffnet werden" << endl; return 2; //ERROR_FILE_NOT_FOUND } file << ct.size() << " "; //Wichtig für ein späteres ct.reserve(...) beim Lesen falls notwendig copy( ct.begin(), ct.end(), ostream_iterator<xINT>(file," ") ); file.close(); xINT::statistik(cout); xINT::reset(); wait(); cout << "\nLesen aus File\n" << endl; file.open("output.txt",ios::in); if(!file) { cout << "Datei konnte nicht geoeffnet werden" << endl; return 2; //ERROR_FILE_NOT_FOUND } unsigned int size; file >> size; cout << "\nAnzahl: " << size << endl; cout << "\nct.clear\n" << endl; ct.clear(); wait(); xINT::statistik(cout); xINT::reset(); wait(); cout << "\nistream_iterator\n" << endl; istream_iterator<xINT> begin(file); // Anfangsiterator auf die Datei istream_iterator<xINT> end; // Enditerator auf die Datei cout << "\ncopy nach ct\n" << endl; copy( begin, end, back_inserter(ct) ); cout << "\ncopy nach cout\n" << endl; copy(ct.begin(), ct.end(), ostream_iterator<xINT>(cout," ") ); cout << endl; wait(); xINT::statistik(cout); xINT::reset(); wait(); return 0; } |
... #include <cassert> using namespace std; const int N = 4; template <class T> class MyStack { private: T elements[N]; int top_; public: MyStack(); ~MyStack(); void push(T i); //Element eingeben T peek(); //Element lesen void pop(); //Element entfernen bool empty(); //MyStack leer? }; template <class T> MyStack<T>::MyStack() { top_=-1; }; template <class T> MyStack<T>::~MyStack(){}; template <class T> T MyStack<T>::peek() { return elements[top_];} template <class T> bool MyStack<T>::empty() { return top_ == -1;} template <class T> void MyStack<T>::push(T i) { assert( top_ < N-1 ); ++top_; elements[top_] = i; } template <class T> void MyStack<T>::pop() { assert(top_ > -1); --top_; } int main() { MyStack<xINT> stack; xINT x; cout << "\nMyStack wird gefuellt\n" << endl; for (int i=1; i<N; ++i) { x.setNum(i); stack.push(x); cout << stack.peek() << endl; } cout << "\nMyStack wird entleert\n" << endl; while ( stack.empty() == false ) { cout << stack.peek() << endl; stack.pop(); } wait(); return 0; } |
const
int N = ...; template <class T> class MyStack { private: T elements[N]; int top_; public: MyStack(); ~MyStack(); void push(const T& i); //Element eingeben const T& peek() const; //Element lesen void pop(); //Element entfernen bool empty() const; //MyStack leer? }; template <class T> MyStack<T>::MyStack() { top_=-1; }; template <class T> MyStack<T>::~MyStack() {}; template <class T> const T& MyStack<T>::peek() const { return elements[top_];} template <class T> bool MyStack<T>::empty() const { return top_ == -1;} template <class T> void MyStack<T>::push(const T& i) { assert( top_ < N-1 ); ++top_; elements[top_] = i; } template <class T> void MyStack<T>::pop() { assert(top_ > -1); --top_; } |
... #include <stack> int main() { { stack<xINT> stack; xINT x; cout << "\nstd::stack wird gefuellt\n" << endl; for (int i=1; i<N; ++i) { x.setNum(i); stack.push(x); cout << stack.top() << endl; } cout << "\nstd::stack wird entleert\n" << endl; while ( stack.empty() == false ) { cout << stack.top() << endl; stack.pop(); } wait(); } wait(); return 0; } |
... #include <cassert> using namespace std; const int N = 4; //Maximale Groesse des Stacks template <class T> class MyStack { private: T* elements; int top_; public: MyStack(int n); ~MyStack(); void push(const T& i); //Element eingeben const T& peek() const; //Element lesen void pop(); //Element entfernen bool empty() const; //MyStack leer? }; template <class T> MyStack<T>::MyStack(int n) { top_=-1; elements = new T[n]; }; template <class T> MyStack<T>::~MyStack(){delete[] elements;}; template <class T> const T& MyStack<T>::peek() const { return elements[top_];} template <class T> bool MyStack<T>::empty() const { return top_ == -1;} template <class T> void MyStack<T>::push(const T& i) { assert( top_ < N-1 ); ++top_; elements[top_] = i; } template <class T> void MyStack<T>::pop() { assert(top_ > -1); --top_; } int main() { { MyStack<xINT> stack(N); xINT x; cout << "\nMyStack wird gefuellt\n" << endl; for (int i=1; i<=N; ++i) { x.setNum(i); stack.push(x); cout << stack.peek() << endl; } cout << "\nMyStack wird entleert\n" << endl; while ( stack.empty() == false ) { cout << stack.peek() << endl; stack.pop(); } wait(); } wait(); return 0; } |
... #include <deque> using namespace std; template <class T> class Stack { private: std::deque<T> ct; //Umhuellter Container public: void push (const T& i) { ct.push_back(i); } void pop() { ct.pop_back(); } const T& peek() const { return ct.back(); } bool empty() const { return ct.empty(); } }; int main() { { Stack<xINT> stack; xINT x; cout << "\nStack wird gefuellt\n" << endl; for (int i=1; i<4; ++i) { x.setNum(i); stack.push(x); cout << stack.peek() << endl; } cout << "\nStack wird entleert\n" << endl; while ( stack.empty() == false ) { cout << stack.peek() << endl; stack.pop(); } wait(); } wait(); return 0; } |
class
Stack { private: std::list<T> ct; //Umhuellter Container public: void push (const T& i) { ct.push_back(i); } void pop() { ct.pop_back(); } const T& peek() const { return ct.back(); } bool empty() const { return ct.empty(); } }; |
template
<class T, class Container = deque<T>> class Stack { private: Container ct; // Umhuellter Container public: void push (const T& i) { ct.push_back(i); } void pop() { ct.pop_back(); } const T& peek() const { return ct.back(); } bool empty() const { return ct.empty(); } }; //jetzt geht z.B.: int main() { { Stack<xINT,vector<xINT>> stack; xINT x; //... |
int
main() { const int N = 5000000; clock_t t1,t2; double ts; xINT x; { Stack<xINT,list<xINT>> stackL; t1 = clock(); //start cout << "\nStackL wird gefuellt\n" << endl; for (int i=1; i<=N; ++i) { x.setNum(i); stackL.push(x); stackL.peek(); } cout << "\nStackL wird entleert\n" << endl; while ( stackL.empty() == false ) { stackL.peek(); stackL.pop(); } t2 = clock(); //end ts = (t2-t1)/static_cast<float>(CLOCKS_PER_SEC); //time span in seconds cout << "time stackL: " << ts << " sec" << endl; } wait(); { Stack<xINT> stackD; t1 = clock(); //start cout << "\nStackD wird gefuellt\n" << endl; for (int i=1; i<=N; ++i) { x.setNum(i); stackD.push(x); stackD.peek(); } cout << "\nStackD wird entleert\n" << endl; while ( stackD.empty() == false ) { stackD.peek(); stackD.pop(); } t2 = clock(); //end ts = (t2-t1)/static_cast<float>(CLOCKS_PER_SEC); //time span in seconds cout << "time stackD: " << ts << " sec" << endl; } wait(); return 0; } |
int main() { const int N = 10000000; clock_t t1,t2; double ts; xINT x; cout << "N = " << N << '\n' << endl; { Stack<xINT,vector<xINT>> stackV; cout << "\nStackV wird gefuellt\n" << endl; t1 = clock(); //start for (int i=1; i<=N; ++i) { x.setNum(i); stackV.push(x); } t2 = clock(); //end ts = (t2-t1)/static_cast<float>(CLOCKS_PER_SEC); //time span in seconds cout << "time stackV: " << ts << " sec" << endl; } wait(); xINT::statistik(cout); xINT::reset(); wait(); { Stack<xINT> stackD; cout << "\nStackD wird gefuellt\n" << endl; t1 = clock(); //start for (int i=1; i<=N; ++i) { x.setNum(i); stackD.push(x); } t2 = clock(); //end ts = (t2-t1)/static_cast<float>(CLOCKS_PER_SEC); //time span in seconds cout << "time stackD: " << ts << " sec" << endl; } wait(); xINT::statistik(cout); xINT::reset(); wait(); return 0; } |
<algorithm>
-- (STL) for defining numerous templates that implement useful
algorithms<deque>
-- (STL) for defining a template class that implements a deque container<functional>
-- (STL) for defining several templates that help construct predicates
for the templates defined<iterator>
-- (STL) for defining several templates that help define and manipulate
iterators<list>
-- (STL) for defining a template class that implements
a doubly linked list container<map>
-- (STL) for defining template classes that implement associative
containers
that map keys to values<memory>
-- (STL) for defining several templates that allocate and free storage
for various container classes<numeric>
-- (STL) for defining several templates that implement useful numeric
functions<queue>
-- (STL) for defining a template class that implements a queue container<set>
-- (STL) for defining template classes that implement associative
containers<stack>
-- (STL) for defining a template class that implements a stack container<utility>
-- (STL) for defining several templates of general utility<vector>
-- (STL) for defining a template class that implements a vector
container<unordered_map>
-- (STL) for defining template classes that implement unordered
associative containers that map keys to values<unordered_set>
-- (STL) for defining template classes that implement unordered
associative containers<hash_map>
-- (STL) for defining template classes that implement hashed
associative containers that map keys to values (includes
an STLport-compatible adapter)<hash_set>
-- (STL) for defining template classes that implement hashed
associative containers (also includes an STLport-compatible adapter)<slist>
-- (STL) for defining a template class that implements
a singly linked list container... #include <memory> //auto_ptr int main() { { xINT* p1(new xINT); //oder: xINT* p1 = new xINT; delete p1; } wait(); { std::auto_ptr<xINT> p2(new xINT); //nicht: std::auto_ptr<xINT> p2 = new xINT; //falsch!!! } wait(); return 0; } |
... #include <memory> int main() { { xINT* p1(new xINT[3]); delete[] p1; } wait(); { std::auto_ptr<xINT> p2(new xINT[3]); //falsch!!! } wait(); return 0; } |
... #include <memory> using namespace std; int main() { { auto_ptr<xINT> p1(new xINT); p1->setNum(333); cout << p1->getNum() << endl; auto_ptr<xINT> p2 = p1; //Das Objekt geht hier von p1 an p2 ueber p2->setNum(42); cout << p2->getNum() << endl; cout << *p2 << endl; cout << p1.get() << endl; cout << p2.get() << endl; } wait(); return 0; } |
... #include <vector> using namespace std; int main() { vector<int>v(1000000000); //10^9 Elemente wait(); return 0; } |
... #include <vector> using namespace std; int main() { try { vector<int>v(1000000000); } catch(...) { cout << "Fehler" << endl; } wait(); return 0; } |
... #include <vector> using namespace std; class std::exception; int main() { try { vector<int>v(1000000000); } catch(exception& e) { cout << "exception" << endl; } //Fangen per Referenz! catch(...) { cout << "Fehler" << endl; } wait(); return 0; } |
Basisklasse: Abgeleitete Klassen:
exception
|
... #include <vector> #include <exception> using namespace std; int main() { try { vector<int>v(1000000000); } catch(exception& e) { cout << typeid(e).name( ) << endl; cout << e.what() << endl; } wait(); return 0; } |
... #include <vector> #include <exception> using namespace std; int main() { try { vector<int>v(1000000000); } catch(bad_alloc& e) { cout << "Gefangener vom Typ bad_alloc: " << e.what() << endl; } catch(exception& e) { cout << "Gefangener vom Typ exception: " << e.what() << endl; } wait(); return 0; } |
... #include <exception> using namespace std; int main() { try { throw "Hallo Welt!"; } catch(bad_alloc& e) { cout << "Gefangener vom Typ bad_alloc: " << e.what() << endl; } catch(exception& e) { cout << "Gefangener vom Typ exception: " << e.what() << endl; } catch(char* str) { cout << str << endl; } catch(...) { cout << "Ich bin der (Fast-)Allesfaenger" << endl; } wait(); return 0; } |
... #include <string> using namespace std; int main() { try { throw string("Hallo Welt!"); } catch(char* str) { cout << "char*: " << str << endl; } catch(string& str) { cout << "string: " << str << endl; } catch(...) { cout << "Ich bin der (Fast-)Allesfaenger" << endl; } wait(); return 0; } |
... #include <vector> class exception; using namespace std; int main() { try { try { vector<int>v(1000000000); } catch(bad_alloc&) { cout << "Ich werfe den Fehler bad_alloc weiter." << endl; throw; } } catch(bad_alloc&) { cout << "Ich fange den Fehler bad_alloc auf."; } wait(); return 0; } |
... #include <vector> class exception; using namespace std; void function() { try { vector<int>v(1000000000); } catch(bad_alloc&) { cout << "Ich werfe den Fehler bad_alloc weiter." << endl; throw; } } int main() { try { function(); //beinhaltet den inneren try/catch/throw-Block } catch(bad_alloc&) { cout << "Ich fange den Fehler bad_alloc auf."; } wait(); return 0; } |
//wie
oben void function() throw (bad_alloc) { //wie oben } int main() { // wie oben } |
//wie
oben void function() throw () //kein Fehlertyp darf geworfen werden { //wie oben } int main() { // wie oben } |
... #include <deque> #include <ctime> #include <cstring> #include <cstdlib> #include <string> #include <iostream> using namespace std ; /************************** Subjekt und Beobachter ***********************************/ class Subject; struct Observer { virtual void Update( Subject* ) = 0; }; class Subject { public: void Attach( Observer* ); void Detach( Observer* ); void Notify(); private: deque<Observer*> observers_; }; void Subject::Attach( Observer* o ) //MeldeAn { observers_.push_back(o); } void Subject::Detach( Observer* o ) //MeldeAb { size_t n = observers_.size(); size_t i; for( i = 0; i < n; ++i ) { if(observers_[i] == o) break; } if(i < n) observers_.erase( observers_.begin() + i ); } void Subject::Notify() //Benachrichtige { size_t n = observers_.size(); for( size_t i = 0; i < n; ++i ) observers_[i]->Update(this); } /************************** Konkretes Subjekt ***********************************/ class Timer : public Subject { public: Timer() { _strtime_s( buffer_ ); }; std::string Timer::GetTime()const {return std::string(buffer_);} void Tick(); private: char buffer_[128]; }; void Timer::Tick() { _tzset(); _strtime_s( buffer_ ); Notify(); } /************************** Konkreter Beobachter ***********************************/ class Clock: public Observer { public: Clock( std::string name, Timer* ); ~Clock(); void Update( Subject* ); std::string getName() const {return name_;} Timer* getSubject() const {return subject_;} private: std::string name_; Timer* subject_; }; Clock::Clock( std::string name, Timer* s ) : subject_(s) { name_ = name; subject_->Attach(this); } Clock::~Clock () { subject_->Detach(this); } void Clock::Update( Subject* s ) //Aktualisiere { if( s == subject_ ) cout << getName() << " zeigt " << subject_->GetTime() << endl; } /************************** Hauptprogramm ***********************************/ int main() { Timer t; //Subjekt const int N = 100; char buffer[20]; Clock* pC[N]; for(int i=0; i<N; ++i) { _itoa_s( i, buffer, 10 ); pC[i] = new Clock( buffer, &t ); //Observer } t.Tick(); wait(); for(int i=0; i<N/2; ++i) { pC[i]->getSubject()->Detach(pC[i]); //Einige Observer melden sich ab } t.Tick(); wait(); for(int i=0; i<N; ++i) { delete pC[i]; } } |
... #include <deque> #include <string> #include <ostream> /************************** Subjekt und Beobachter ***********************************/ class Subject; struct Observer { virtual void update( Subject* ) = 0; }; class Subject { public: void attach( Observer* ); void detach( Observer* ); void notify(); private: std::deque<Observer*> observers_; }; void Subject::attach( Observer* o ) //MeldeAn { observers_.push_back(o); } void Subject::detach( Observer* o ) //MeldeAb { size_t n = observers_.size(); size_t i; for( i = 0; i < n; ++i ) { if(observers_[i] == o) break; } if(i < n) observers_.erase( observers_.begin() + i ); } void Subject::notify() //Benachrichtige { size_t n = observers_.size(); for( size_t i = 0; i < n; ++i ) observers_[i]->update(this); } /************************** Konkretes Subjekt ***********************************/ class MailServer : public Subject { public: MailServer( std::string name ): name_(name){} void neuerNewsletter() { notify(); } std::string getName() const {return name_;} private: const std::string name_; }; /************************** Konkreter Beobachter ***********************************/ class EmailKonto: public Observer { public: EmailKonto( std::string name, MailServer* ); ~EmailKonto(); void update( Subject* ); std::string getName() const {return name_;} MailServer* getSubject() const {return subject_;} private: const std::string name_; MailServer* subject_; }; EmailKonto::EmailKonto( std::string name, MailServer* s ) : name_(name), subject_(s) { subject_->attach(this); } EmailKonto::~EmailKonto () { subject_->detach(this); } void EmailKonto::update( Subject* s ) //Aktualisiere { if( s == subject_ ) std::cout << "Hallo Herr Nr. " << getName() << ", ein neuer Newsletter von " << subject_->getName()<< " ist erschienen." << std::endl; } /************************** Hauptprogramm ***********************************/ int main() { MailServer s("HenkesSoft3000"); //Subjekt "MailServer" const int N = 5; char buffer[10]; EmailKonto* pMK[N]; for(int i=0; i<N; ++i) { _itoa_s( i, buffer, 10 ); pMK[i] = new EmailKonto( buffer, &s ); //Mailkonten melden sich an } s.neuerNewsletter(); wait(); for(int i=0; i<(N-2); ++i) { pMK[i]->getSubject()->detach(pMK[i]); //Zwei Mailkonten melden sich ab } s.neuerNewsletter(); wait(); for(int i=0; i<N; ++i) { delete pMK[i]; } } |
//
MySingleton.h
class MySingleton |
// MySingleton.h class MySingleton : public Singleton<Klasse_fuer_vereinzelte_Objekte> |