Vorbemerkungen

Wie eingangs schon beschrieben kann und soll dieses Tutorial kein C-Lehrbuch sein. Es ist für das Verstehen dieses Tutorials auf jeden Fall von Vorteil, wenn Kenntnisse in einer höheren Programmiersprache vorhanden sind. Am besten natürlich C. Wer über Kenntnisse einer objektorientierten Sprache wie JAVA, C++ oder C# verfügt, kann sich sofort auf den praktischen Teil stürzen. Für jeden, der über keine oder noch wenig Programmierkenntnisse verfügt, ist zu empfehlen, ein entsprechendes C/C++ Nachschlagewerk (Lehrbuch oder online Tutorial) diesem Tutorial beizustellen und jede Klammer sowie jeden Ausdruck, der in den angebotenen Quelltexten unklar ist, nachzuschlagen.

Objektorientierte Programmiersprachen

Ausgangspunkt für das Verstehen einer objektorientierten Programmiersprache ist immer das objektorientierte Basiskonzept (Paradigma). Das Basiskonzept stellt sozusagen das SOLL und die konkrete Sprache das IST dar. Gehen Sie davon aus, dass eigentlich in keiner derzeit verfügbaren objektorientierten Sprache auch alle in der Theorie formulierten Konzepte bereits komplett umgesetzt sind. Man sollte sich auf jeden Fall davor hüten, von den Möglichkeiten und den Einschränkungen einer konkreten Sprache auf das Konzept zu schließen. Wesentliche Aspekte objektorientierter Sprachen sollen im Folgenden anhand der Sprache C++ aufgezeigt werden. Für das Verständnis von C++ ist weiterhin wichtig zu wissen, das C++ die Sprache C beinhaltet. C++ ist die objektorientierte Erweiterung der Sprache C.

der Sprachumfang von C (Auszug)

// Schlüsselworte ..........................................
break		double		int		struct
case		else		long		switch
char		extern		return		unsigned
const		float		short		signed	
continue	for		void		sizeof
default		if		sizeof		volatile
do		while		main
// Operatoren ..............................................
+		-		*		/
=		++		--		
<<		>>		!		&
|		^		~		%
==		>		<		<=
>=		&&		||		!=

wesentliche C-Steuerflusskonstrukte

C folgt dem Basiskonzept der Strukturierung. Das bedeutet nichts weiter, als das auf die Sprunganweisung (vgl. Assembler, GOTO, JUMP, usw.) verzichtet wird, um einen Algorithmus zu erstellen. Es werden nur drei algorithmische Grundstrukturen benötigt, um jede Programmlogik zu realisieren. Das sind:

  • die Sequenz, Anweisungen werden nacheinander ausgeführt
  • die Iteration (Wiederholung, Schleife), Anweisungen werden wiederholt ausgeführt
  • die Alternative, bestimmte Anweisungen werden entsprechend einer Bedingung anstatt anderer Anweisungen ausgeführt

In den strukturierten Sprachen gibt es zwar noch weitere Spielarten dieser drei Grundstrukturen, aber dem Wesen nach gibt es tatsächlich nur diese drei. Im Folgenden soll dargestellt werden wie diese Algorithmusbausteine in C und dann natürlich auch in C++ notiert werden. Beachten Sie die geschweiften Klammern! Diese begrenzen einen Anweisungsblock und sollten immer, besonders am Anfang, diszipliniert gesetzt werden.

// Blöcke in C und C++
{	// BEGIN
	// Blockinhalt
}	// END

Blöcke können zusätzlich einen Namen und Parameter erhalten. Das sieht dann in etwa so aus:

name ( parameter )
{	// BEGIN
	// Blockinhalt
}	// END

Diese Namen können sogenannte reservierte Worte, also Schlüsselworte der Sprache C/C++ sein. Damit wird dem bezeichneten Block eine bestimmte Funktionalität zugewiesen. Darüber hinaus kann der Programmierer Blöcke bauen, die einen eigenen vom Programmierer festgelegten Namen erhalten. Diese Blöcken können dann unter dem festgelegten Namen aufgerufen werden. In C nennt man solche Blöcke Funktionen. Den Klammern kommt in C also eine konstituierende Rolle zu, die es zu verinnerlichen gilt.

Das Weglassen von Klammern in bestimmten Fällen sind eben genau Sonderfälle und diese sollte man sich als Einsteiger erst mal sparen. Übrigens gibt es die Blockbildung in allen strukturierten Sprachen. Manchmal sind das statt Klammern Schlüsselworte wie BEGIN oder END. Das Gleiche gilt für das Semikolon. Ein Semikolon ist in C das Endekennzeichen einer Anweisung und für den Compiler extrem wichtig. Notieren Sie eine Anweisung immer in einer eigenen Zeile und schließen diese immer mit einem Semikolon ab. Das Einrücken der Anweisungen mit einem TAB innerhalb eines Blocks hilft den Überblick zu bewahren.

int A,B,C;
 
// eine Sequenz ..............................................
{
	A = 1;		// führe zuerst A
	B = 2;		// dann B
	C = A+B;	// danach C aus A und B berechnen
}
// eine Wiederholung .........................................
while ( A < 100 )	// wiederhole ( solange )
{			
	A = A + 1;	// diese Anweisungen
}			
// eine Alternative ..........................................
if ( A == 0)		// wenn ( das wahr ist )
{
	C = B;		// dann führe diese Anweisungen aus
}
else			// sonst
{
	C = A;		// führe diese Anweisungen aus
}
// -----------------------------------------------------------
// ausgewählte Spielarten
// -----------------------------------------------------------
 
// Zählschleife ..............................................
for ( uint8_t i = 0; i<100; i++)
{
	// was auch immer genau 100 mal getan werden muss
}
// fußgesteuerte Schleife ....................................
do {
	// etwas was mindestens einmal oder öfter nötig ist
} while ( notReady );
 
// bedingte Anweisung .......................................
if ( ok )
{
	// etwas alternativloses
}
// Fallunterscheidung .............
switch (fall)
{
	case 1:  { 
			// Fall 1
		 } break;
	case 2:  { 
			// Fall 2
		 } break;
	default: { 
			// Standardfall
		 } break;
}

zusätzlicher Sprachumfang von C++ (Auszug)

bool 		catch  		false 		enum
class 		new 		delete 		public 		template 
virtual 	operator 	private 	protected 	this
namespace 	using 		true		throw 		try

Wie wir sehen, ist der eigentliche Sprachumfang von C übersichtlich und die Erweiterung, um zur Sprache C++ zu kommen, vergleichsweise gering. Was dem Lernenden als umfangreich erscheint, sind die hinzukommenden Bibliotheken, welche vorgefertigte Funktionen anbieten. Des Weiteren ist ersichtlich, dass eine objektorientierte Programmiersprache ihre strukturierten Vorgänger nicht ablöst, sondern auf deren Konzepten und Schlüsselworten aufbaut und diese auch übernimmt. Die Botschaft lautet also, das alles, was man mit C machen kann, nach wie vor auch in C++ funktioniert . Eine objektorientierte Programmiersprache muss also zusätzlich nur die Ausdrucksmittel zur Realisierung der objektorientierten Basiskonzepte anbieten. Zu einem objektorientierten Programm kommt man nicht einfach durch Verwendung eines bestimmten Compilers, sondern einzig durch die Art und Weise, wie man das Programm aufbaut. Im Folgenden vorab wichtige C++ Konstrukte, welche ausgewählte besondere Merkmale einer objektorientierten Sprache aufzeigen. Im Verlauf des Tutorials werden wesentliche Aspekte des Gezeigten Schritt für Schritt besprochen.

Deklarieren von Klassen in C++

Es ist ein Anwendungsprogramm mit dem Namen Applikation (englisch: Application) zu entwickeln. Die Anwendung soll zunächst geplant und dann programmiert werden und letztlich benötigen wir noch eine Instanz von diesem Programm.

// Klasse Name { Bauplan } Instanz;
class Application
{
 
} app; 

Vererbung in C++

Die Applikation ist eine Mikrocontrolleranwendung. Diese soll alle Möglichkeiten der vorhandenen Klasse Controller besitzen. Somit erbt die Applikation am besten alle Merkmale vom Controller.

// Klasse Name : Sichtbarkeit Basisklasse { Bauplanerweiterung } Instanz;
class Application : public Controller
{
 
} app; 

Operationen in C++

Der Controller wird eingeschaltet und arbeitet dann fortlaufend taktgesteuert. Oh ja, wir erinnern uns dunkel. Subjekt und Prädikat. WER (der Controller) macht WAS (wird eingeschaltet, arbeitet)… Dafür sollte es jetzt Operationen in der Klasse geben.

// Klasse Name : Sichtbarkeit Basisklasse { Bauplanerweiterung } Instanz;
class Application : public Controller
{
   // Sichtbarkeit : RückgabeTyp name (Parameter) { Code; }
   public: void onStart()
   {
      // alles was beim Hochfahren getan werden muss
      // danach geht es zur Mainloop in der Basisklasse Controller
   }
   // Sichtbarkeit : RückgabeTyp name (Parameter) { Code; }
   public: void onWork()
   {
      // alles was fortlaufend getan werden muss
      // die Mainloop liegt in der Basisklasse Controller
      // von dort aus wird onWork fortlaufend aufgerufen (getriggert)
      // hier also KEINE Unendlichschleife !!!
   }
} app; 

Aggregationen und Kapselung in C++

Es soll eine LED angeschlossen werden. An diese LED wollen wir niemand anderen heran lassen. Wir schützen diese vor unberechtigtem Zugriff.

// Klasse Name : Sichtbarkeit Basisklasse { Bauplanerweiterung } Instanz;
class Application : public Controller
{
   // Sichtbarkeit : Typ name;
   protected: LED led;
 
   public: void onStart()
   {
      // ...
   }
   public: void onWork()
   {
      // ...
   }
} app; 

Nachrichten in C++

Die LED ist eine fertige Klasse aus dem Framework. Wir müssen der LED mitteilen, an welchem Port-Pin sie angeschlossen ist und wir wollen sie einschalten.

// Klasse Name : Sichtbarkeit Basisklasse { Bauplanerweiterung } Instanz;
class Application : public Controller
{
   // Sichtbarkeit : Typ name;
   protected: LED led;
 
   public: onStart()
   { 
      // instanzName . nachricht ( Parameter );
      led.config(pin22);
   }
   public: onWork()
   {
      // instanzName . nachricht ( );
      led.on();
   }
} app; 

Zwischenfazit

Bei diesem kurzen Ausflug in die objektorientierte Art und Weise Programme zu schreiben, ist wohl deutlich geworden, dass es sehr darauf ankommt, sich ein bestimmtes Muster anzugewöhnen, Systeme zu betrachten und darüber nachzudenken. Objektorientierung beginnt im Kopf! Übrigens ist es hilfreich, das zu programmierende System in kurzen einfachen Sätzen zu beschreiben oder diese laut vor sich hin zu sagen.

Nächstes Thema

objektorientierte_programmiersprachen.txt · Zuletzt geändert: 2013/12/31 10:06 von huwi