Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.1 Informatik I Einführung Algorithmus, Programmiersprache, Compiler und Linker Datentypen Kontrollstrukturen Präprozessoranweisungen Libraries Funktionen und Klassen Objektorientierte Programmierung Inhalte 08.05.2011 Dr.-Ing. habil. Jörg Wollnack INFOB.2 Große Programmprojekte mit kommerziellen Libraries haben viele Abhängigkeiten. Veränderungen der Programme können unübersichtliche Seiteneffekte bewirken, die eine Weiterentwicklung unter wirtschaftlichen Gesichtspunkten nicht mehr möglich macht. Die Initialisierung und Weitergabe von großen Datenobjekten wird schnell unübersichtlich. Eine Verwendung von globalen Datenobjekten kann hierbei helfen, macht diese jedoch für sämtliche Module sichtbar. Dies ist häufig nicht erwünscht und bietet Gefahren bei nicht vom Entwickler geplanten Datenänderungen durch den Programmentwickler (Zugriff kann nicht gesperrt werden). Die Kapselung der Daten über globale static Objekte der Module ist zwar möglich, jedoch nicht konsequent genug. Probleme komplexer Programmsysteme Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.3 Der Programmentwickler soll nur die für die Anwendung relevante Objekte sehen und nutzen können. Dies erhöht die Code-Sicherheit und Wirtschaftlichkeit der Programmerstellung (protected-Objekte). Der Zugriff auf Datenobjekte soll nur über definierte Interface in zulässiger Weise erfolgen (Memberfunktionen). Zwischen Datenobjekten und deren Operatoren existieren Verwandtschafts-, Teil- und Obermengenrelationen, die beim Programmentwurf berücksichtigt werden sollen. Dies führt zur Wiederverwendbarkeit und einfacheren Wartung von komplexen Programmsystemen. Objektorientierte Programmierung I Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.4 Die strukturelle Verwandtschaft, die zumeist auch in der menschlichen Schreibweise zum Ausdruck gebracht wird, soll sich möglichst in der Programmnotation wiederfinden. Dies führt zur besseren Lesbarkeit durch den Menschen und damit zu sichereren und wirtschaftlicheren Programmsystemen. Die vom Menschen entwickelten Algebren sollen in einer möglichst ähnlichen Notation im Programmcode ausgedrückt werden können. C++ kommt diesem Ziel durch überladbare Memberfunktionen und Operatoren recht nahe. Die Rangfolgen der Operatoren können jedoch nicht geändert werden. Objektorientierte Programmierung II Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.5 + - * / % ^ ! = < > += –= ^= &= |= << >> <<= <= >= && || ++ –– () [] new delete & | ~ *= /= %= >>= == != , –> –>* In C++ überladbare Operatoren. Rangordnung bleibt unverändert. Scientific Pascal war bereits vor ca. 20 Jahren weiter. Die Rangordnung von Operatoren konnte vom Entwickler festgelegt werden. Dies erfordert jedoch eine fundierte mathematische Ausbildung. Objektorientierte Programmierung III Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.6 Einstelliger/unärer Operator (op) y = op x Zweistelliger/binärer Operator y = u op v Warum nicht auch so programmieren? op:= Operator auf dem Objekt Algebra reeller und komplexer Zahlen y = (a + c) + u ⋅ (b + d / e + g)v Vektoralgebra y = (a + c) + u ⋅ (b + d × e + g) Matrixalgebra Y = M−1 ⋅ (A + C)t + Un ⋅ (b + d) Objektorientierte Programmierung IV Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.7 Der Programmentwurf soll auf einer höheren Abstraktionsebene möglich sein. Die hierfür erforderliche Übersetzungsarbeit soll nach Implementation der Objekte der Compiler und nicht der Mensch vollziehen. Dies erhöht Sicherheit und Wirtschaftlichkeit von komplexen Programmsystemen. Die Implementation z.B. einer Vektor- und Matrixalgebra kann für double, long double, complex und long complex Datentypen erfolgen. Die Anpassungen an diese Varianten soll vom Compiler und nicht von Menschen erfolgen. Dies erhöht Sicherheit und Wirtschaftlichkeit von komplexen Programmsystemen. In C++ lassen sich hierfür Templates heranziehen (Template := engl. Vorlage). Objektorientierte Programmierung V Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.8 Die objektorientierte Programmierung führt vermehrt dazu, dass Informatiker erst denken und dann programmieren sollten (Im Grunde gilt dies natürlich für alle Menschen). Objektorientierte Programmierung VI Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.9 Vektor- und Matrixanordnungen sind für beliebige Datenobjekte zweckmäßig (Rot,Grün,Blau)-Vektor eines Bildpunktes eines y 2-dimensionalen Bildes, Tabelle von Namen, Anordnung von Zahlen, Jacobi-Matrix von Vektorfunktionen über Templates umsetzen). Hierauf fußend könnte man für double, long double, complex und long complex Zahlen eine Matrixalgebra aufbauen (Ableitung). x Diese Beispiele zeigen den Bedarf sowohl für das Ableiten von Klassen aus Basisklassen (Vektor- und Matrixanordnung Vektor- und Matrixalgebra) als auch Templates (Einsetzen verschiedener Datentypen in Programmvorlagen). Beispiele für Ableitungen und Templates Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.10 y V( x, y) ≡ R V = G , R, G, B ∈{0,...,255} B ( x, y) ∈{0,..., xMax }×{0,..., yMax } x Vektorabbildungen in der Bildverarbeitung Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.11 class [tag [: base-list ]] { member-list } [declarators]; // Definition/Deklaration (Header) [class] tag declarators; // Instanz (Applikation) Typ tag::member(arg-list) // Implementation (Modul) { statement; } Syntax einer Klasse Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.12 Klassen sind verwandt mit Strukturen, lassen jedoch eine konsequente Strukturierung der Objekte zu. Klassen und Strukturen Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.13 class CName : BasisKlasse { protected: Typ m_TVarname; … private: Typ … FunktionName(argliste); // abgeleitetes Klassenobjekt // public CObject für Windows verwenden // gekapselte Datenobjekte // Nur für Memberfunktionen public: CName(); CName(argliste); CName(const CName& Varname) ~CName() // öffentliches Interface // void Konstruktor (default) // Konstruktor (Initialisierung) // Copy-Konstruktor (Initialisierung) // Destruktor Typ … }; // Memberfunktion FunktionName(argliste); Definition einer Klasse (Header) Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.14 CName::CName() { statement; } // void Konstruktor // Wird benötigt, wenn Objekt Element eines // C-Vektors sein kann. CName::CName(argliste) { statement; } // Konstruktor // Z.B. dynamische Datenobjekte anlegen // Initialisierung usw. ~CName::CName() { statement; } // Destruktor // Z.B. dynamische Datenobjekte frei geben Typ CName::FunktionName(argliste) { statement; } // Memberfunktion Implementation einer Klasse (Modul) Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.15 int main() { CName InstanzName(Arg); Typ TReturnValue; // Objekt anlegen CName * pInstanzName = new CName[4]; // Vektor mit void-Objekten anlegen TReturnValue = InstanzName.FunktionName(Arg); // Memberfunktion von Objekt pInstanzeName[2].CName(Arg); // Element des Vektors anlegen TReturnValue = pInstanzeName[2].FunktionName(Arg); // Memberfunktion von Objekt delete [] pInstanzName; }; // Speicher frei geben Instanz einer Klasse (Applikation) Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.16 Konstruktoren, Destruktoren, Memberfunktionen und Operatoren repräsentieren Methoden der Klasse/des Objekts. Sie können explizit oder implizit als inline definiert werden. Im ersten Fall wird das Schlüsselwort inline der Definition vorangestellt. Die Implementation der inline-Funktion sollte in der selben Header-Datei erfolgen, da der Compiler diese kennen muss. Kurze inline Methoden können direkt innerhalb der Klasse implizit implementiert werden. Das Schlüsselwort ist hierbei nicht zwingend erforderlich. Methoden Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.17 Konstruktoren: Vollziehen eine Initialisierung des Objekts und haben den Namen der Klasse. Konstruktoren müssen sich durch ihre Signatur unterscheiden (Anzahl, Typ und Reihenfolge der Parameter) (CClassName(Argliste)). Default-Konstruktor: Ist ein Konstruktor ohne Parameter und setzt die Elemente des Objekts auf Standardwerte. Wird dieser nicht implementiert, so erzeugt der Compiler eine Minimalversion ohne Initialisierung der Elemente. Existiert mindestens ein Konstruktor, so muss der Default-Konstruktor explizit definiert werden. Sollen die Objekte als Vektorelemente dienen (new CClassName[…]), so ist ein Default-Konstruktor erforderlich (CClassName(void)). Copy-Konstruktor: Initialisiert ein Objekt mit einem anderen desselben Typs und muss vom Entwickler implementiert werden. Dieser Konstruktor wird aufgerufen, wenn ein Call by Value erfolgt (CClassName(CClassName& x)). Konstruktoren und Destruktoren I Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.18 Destruktor: Der Destruktur vollzieht einen geregelten Abbau des durch einen Konstruktor aufgebauten Objekts. Z.B. müssen Elemente, die Speicherplatz über eine Konstruktor reservieren, wieder freigeben werden. Sein Name ist identisch mit dem Namen der Klasse mit der Tilde ~ als Präfix und er hat keine Argumente (~CClassName()). Der Aufruf erfolgt automatisch, wenn die Lebensdauer eines Objekts beendet ist. Bei einem lokalen Objekt am Ende eines Blockes und bei globalen oder static Objekten am Ende des Programms. Der Aufruf erfolgt auch, wenn mit delete ein mit new erzeugtes Objekt zerstört wird. Konstruktoren und Destruktoren II Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.19 Zuweisungs-Operator: Kopiert ein Objekt in ein existierendes Objekt gleichen Typs. Dieser Operator muss vom Entwickler implementiert werden. Memberfunktionen: Haben Zugriff auf die Elemente des Objekts. this-Pointer: Ein konstanter Zeiger auf das Objekts innerhalb einer Memberfunktion. Konstruktoren und Destruktoren II Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.20 Rückgabe als Kopie: Ist rechenzeitintensiv, da Daten auf über den Stack übergeben werden. Insofern nur für kleine Objekte sinnvoll. Die Kopie vollzieht der copy-Konstruktor. Rückgabe als Referenz: Wird intern als Pointer zurückgegeben und ist deshalb effizient. Die Lebensdauer des Objekts darf nicht lokal sein. Eine Deklaration als static Objekt wäre denkbar, bietet jedoch die Gefahr von Quereffekten. Rückgabe als Pointer: Diese explizite Pointer Rückgabe ist analog zur Referenz, weshalb auch hier die Lebensdauer des Objekts nicht lokal sein darf. Objekte als return-Werte Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.21 template < [TypenListe] [,[ArgListe]] > Deklaration template <class T, int i> class TestClass // Deklaration { public: char buffer[i]; T testFunc(T* p1 ); }; (Header) template<class T, int i> T TestClass<T,i>::testFunc(T* p1) { return *(p1++); }; // Implementation (Modul) TestClass<char, 5> ClassInst; // Instanz (Applikation) Templates Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.22 template <class T> void Swap(T& a,T& b) { T c = a; a = b; b = c; } Funktions-Template Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.23 template <class T, int i> class TemplClass { public: TemplClass(void); ~TemplClass(void); int MemberSet(T a, int b); private: T TArray[i]; int ArraySize; }; Klassen-Template Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.24 #define min(i, j) (((i) < (j)) ? (i) : (j)) template<class T> T min (T i, T j) { return ((i < j) ? i : j) } There is no way for the compiler to verify that the macro parameters are of compatible types. The macro is expanded without any special type checking. The i and j parameters are evaluated twice. For example, if either parameter has a postincremented variable, the increment is performed two times. Because macros are expanded by the preprocessor, compiler error messages will refer to the expanded macro, rather than the macro definition itself. Also, the macro will show up in expanded form during debugging [Microsoft]. Makros versus Templates Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.25 CString::CString(char* cp); Konvertierungskonstruktor (Member) Klasse Anderer Datentyp Konvertierungsfunktion (Member) operator Typ(void) const; Konvertierung für Klassen/Objekte I Dr.-Ing. habil. Jörg Wollnack 08.05.2011 INFOB.26 Ist der Zieltyp eine Klasse, so sollten Konvertierungskonstruktoren eingesetzt werden. Soll das Objekt in der die Zielklasse unverändert sein, so sind Konvertierungsfunktionen vorzuziehen. Mehrdeutigkeiten bei den Konvertierungen können durch explizite Konvertierungen ausgeschlossen werden. Mögliche Mehrdeutigkeitsproblem lassen sich mindern, indem man Methoden AsTyp(void) implementiert, mit denen man eine explizite Typenumwandlung vollziehen kann. Konvertierung für Klassen/Objekte II