const Zwei Schlüsselwörter bei der Deklaration von Variablen und Member-Funktionen haben wir noch nicht behandelt: const und static. Eine const Variable kann ihren Wert nicht ändern: const double pi = 3.1415; C++ kennt Konstanten. Also sind #define-anweisungen als Konstantenersatz überflüssig und zu vermeiden. Wenn Argumente von Funktionen konstante Variablen (insbesondere konstante Referenzen und Pointer) sein können, dann sollte man sie aus Sicherheitsgründen unbedingt konstant machen. Mathematische und physikalische Konstanten muss man nicht selbst definieren: For example function boost::math::constants::pi<float>() returns the maximally accurate PI value for float type. Even though they are functions, they don t really calculate the value at run-time; they just return a constant. I think this is much better than M_PI. Und: http://www.gnu.org/software/gsl/manual/html_node/physical-constants.html Eine const deklarierte Member-Funktion einer Klasse kann den Zustand einer Instanz dieser Klasse nicht ändern (kann keine Member-Variablen der Instanz verändern und kann keine nicht-konstanten Funktionen aufrufen). Beim Design einer Klasse sollte man sich gleich überlegen, welche Methoden konstante Werte zurück liefern, und welche Methoden selbst konstant gemacht werden können. Je mehr Rückgabewerte, Argumente und Methoden als konstant deklariert werden können, je besser. Wenn man Konstanten braucht, dann sollte man das dafür vorgesehene Sprachmittel const type name auch benutzen!
static Das Schlüsselwort static hat unterschiedliche Bedeutung, je nachdem wo es steht: Innerhalb einer Funktion vor einer Variablen-Deklaration: Die Variable wird nicht bei jedem Aufruf der Funktion initialisiert, sondern nur einmal beim Programmstart. #include <iostream> void teststatic() { int counter = 0; std::cout << counter now is << counter << std::endl; counter++; return; int main() { for (int i=0; i<10; i++) teststatic(); return 0; #include <iostream> void teststatic() { static int counter = 0; std::cout << counter now is << counter << std::endl; counter++; return; int main() { for (int i=0; i<10; i++) teststatic(); return 0; In einer Klassen-Definition vor einer Member-Variablen-Deklaration: Alle Instanzen der Klasse teilen sich die Variable. static member variables existieren schon bevor der erste Konstruktor der Klasse aufgerufen wurde. static member variables werden.cc-file initialisert: int TestStaticClass::counter = 0;
static Schreibt eine TestStaticClass Mit einer static member variable int counter Mit einem default ctor, der die eryeugten Instanzen zählt Mit einer int counted() Methode, die den Zählerstand zurück liefert Schreibt ein main()-programm Das 7 Instanzen von TestStaticClass erzeugt Das nach dem Erzeugen jeder Instanz den Zähler abfragt und ausgibt. Nicht vergessen: den Zähler in TestStaticClass.cc initialisieren!
static Das Schlüsselwort static hat unterschiedliche Bedeutung, je nachdem wo es steht: Vor einer Member-Funktions-Deklaration: static member functions existieren ausserhalb aller Instanzen der Klasse, und es gibt sie folglich schon bevor der erste ctor der Klasse aufgerufen wurde (genau wie bei einer static member variable) Aufruf einer static member function: int result = TestStaticClass::nofCalls(); Baut in TestStaticClass eine static member function int nofcalls() ein, die zurückliefert, wie oft sie schon aufgerufen wurden. Testet nofcalls() in eurem main(). Wir können eine Variable in einer Funktion so deklarieren, dass sie ihren Wert zwischen den Aufrufen behält. Wir können sicher stellen, dass es von einer Member-Variablen nur eine Kopie gibt. Wir können dafür sorgen, dass es von einer Member-Funktion nur eine Kopie gibt. Wie können wir erreichen, dass es von einer Klasse höchstens eine Instanz gibt?
static Das Schlüsselwort static hat unterschiedliche Bedeutung, je nachdem wo es steht: Vor einer Member-Funktions-Deklaration: static member functions existieren ausserhalb aller Instanzen der Klasse, und es gibt sie folglich schon bevor der erste ctor der Klasse aufgerufen wurde (genau wie bei einer static member variable) Aufruf einer static member function: int result = TestStaticClass::nofCalls(); Baut in TestStaticClass eine static member function int nofcalls() ein, die zurückliefert, wie oft sie schon aufgerufen wurden. Testet nofcalls() in eurem main(). Wir können eine Variable in einer Funktion so deklarieren, dass sie ihren Wert zwischen den Aufrufen behält. Wir können sicher stellen, dass es von einer Member-Variablen nur eine Kopie gibt. Wir können dafür sorgen, dass es von einer Member-Funktion nur eine Kopie gibt. Wie können wir erreichen, dass es von einer Klasse höchstens eine Instanz gibt? Mit dem Singleton Design Pattern
Design Patterns Design Patterns sind bewährte Design-Lösungen zu bekannten, häufiger auftretenden Problemen in der Softwareentwicklung. Warum Design Patterns? Zeitersparnis: Die Lösung des Problems wurde schon von anderen erarbeitet Fehlerfreiheit: Design Patterns sind bewährte, getestete Lösungen Vereinfachte Weiterentwicklung: Andere Entwickler erkennen eine Design Pattern wieder und verstehen dadurch fremden, geerbten Code schneller Welche Patterns gibt es? Creational design patterns Abstract Factory: Creates an instance of several families of classes Builder: Separates object construction from its representation Factory Method: Creates an instance of several derived classes Object Pool: Avoid expensive acquisition and release of resources by recycling objects that are no longer in use Prototype: A fully initialized instance to be copied or cloned Singleton: A class of which only a single instance can exist Structural design patterns Adapter: Match interfaces of different classes Bridge: Separates an object s interface from its implementation Composite: A tree structure of simple and composite objects Decorator: Add responsibilities to objects dynamically Facade: A single class that represents an entire subsystem Flyweight: A fine-grained instance used for efficient sharing Private Class Data: Restricts accessor/mutator access Proxy: An object representing another object
Design Patterns Welche Patterns gibt es? Behavioral design patterns Chain of responsibility: A way of passing a request between a chain of objects Command: Encapsulate a command request as an object Interpreter: A way to include language elements in a program Iterator: Sequentially access the elements of a collection Mediator: Defines simplified communication between classes Memento: Capture and restore an object's internal state Null Object: Designed to act as a default value of an object Observer: A way of notifying change to a number of classes State: Alter an object's behavior when its state changes Strategy: Encapsulates an algorithm inside a class Template method: Defer the exact steps of an algorithm to a subclass Visitor: Defines a new operation to a class without change... Unser Problem war es sicher zu stellen, dass es nur eine Instanz einer Klasse geben darf: Singleton: A class of which only a single instance can exist Lösung: Niemand ausser einer Methode der selben Klasse darf den ctor der Klasse aufrufen können: Der ctor wandert von public nach protected.
Design Patterns // singleton.h class Singleton { public: static Singleton& instance() { // das einzige Objekt dieser Klasse erzeugen und als Referenz zurückgeben // singleton ist eine statische Variable in einer statischen Member-Funktion static Singleton singleton; return singleton; Singleton::instance().doSomething(); void dosomething() { protected: Singleton() { // Auch der Copy-Konstruktor muss protected sein, damit niemand Kopien macht Singleton(const Singleton& other) { ; Es gibt noch weitere, leicht andere Implementierungen des Singleton Patterns. Macht aus der TestStaticClass ein Singleton. Lasst counted() zählen, wie oft es aufgerufen wurde. Holt euch in main() eine Reihe von TestStaticClass-Referenzen, und gebt jedesmal den Wert von counted() aus (um zu testen, dass ihr immer mit der selben Instanz redet).