Objekt bearbeiten

Klasse

class MidiData {
.     public: 
.            // varibale
.            int pin;
.            double version;
.            int wait;        // in ms
.
.            // functions
.            MidiData(int pin, double version, int wait);   
.            string readStream( steam io);
.            string extractdata( string s);
}

Objekt definieren

MidiData system_2{ 8, 14.04, 5 }

system_2 ist ein Objekt der Klasse MidireadData. Im Objekt ist definiert, wo und mit welcher Version Midi gelesen wird.

Objeket bearbeiten

system_2.pin = 10;    // change data pin
system_2.wait = 10;   // change wait time

Zur Verarbeitung der Klasse wurden extra Memberfunktionen definiert.

string in_pin8 = system_2.readStream( input_8);
string data_pin8 = system_2.extractdata( in_pin8);

Über die Objektvariable system_2 können die Memberfunktionen aufgerufen werden.

 

Constructor C++

Eine Member-Funktion mit demselben Name wie die Klasse selbst, ist ein Constructor.

1. Konstruktor ohne Funktionen———————————————–

class MidiData {
. public: 
.     int pin;
.     double version;
.     int wait;        // in ms
.     MidiData(int pin, double version, int wait);  //Construct
.
}

Ein Objekt der Klasse kann nicht ohne Wertzuweisung definiert werden, eine Initialisierung ist zwingend notwendig beim Bilden eines Objektes. Die Initialiserung kann über eine List ober über den Constructor erfolgen:

MidireadData system_1 = { 13,  14.04, 10}  // list

MidireadData system_2 { 8, 14.04, 5 }  // constructor usually
MidireadData system_2( 8, 14.04, 5 )   // constructor old style

MidireadData system_3 = MidireadData{ 10, 14.04, 10 } //special

In der Initialisierung müssen alle Member-Variablen definiert werden.
Vgl. Bjarne Kapitel 9.4.2

2. Konstruktor für Klasse mit Funktionen ——————————-

class Date{
.      public:
.         // constructor
.         Date( int year, int month, int day);  
.         // member-functions
.         void add_day( int n);
.         int month();       // check error of number        
.
.      private:
.         int year, month, day;

};

Konstruktor mit Funktion:

Date::Date(int y_1,int m_1,int d_1)      
     : month( month1) {}

Class: public and private

Was eine Klasse ist
– Eine Klasse ist ein selbst definierter Datentyp
– Man erfindet eine Klasse nur, weil man sie für etwas braucht.
– Um das umzusetzen, braucht man Variablen und Funkitonen
– Damit man nicht alles von Hand schreiben muss, importiert
.  man oft Funktionen von Bibliotheken (oder anderen Klassen)

Struktur

class <Name> {
.     public: 
.            <type> <var>;
.            <type> <member_function>(<arguments);
.
.     private:
.            <type> <utility_functions>(<argument>);    
} ;

public:
–  Alles, warum die Classe definiert wurde. Der Public-Teil dient
.  dem direkten bearbeiten (nutzen) der Klasse.
–  Den Public-Teil nennt man auch das Interface.
–  Die Funktionen im public heissen member functions. Nur diese
.  Funktinen sind von aussen zugänglich (sichtbar)

private:
–  Hilfsfunktionen und Hilfsvaraiabeln.

Bilden eines Objektes
Eine Klasse kreierte man, weil man sie braucht. Damit man sie brauchen kann, müssen der Klasse Werte zugewiesen werden, dies geschieht im Constructor. In Python wird der Konstruktor durch die Funktion init in der Klasse definiert.

class <Name>(<argument>):

.    def __init__(self):  
.        // set variables
        
.   def <function_a> (self):
.       // Code

In C++ wird der Konstruktor nach der Klasse gebildet.

C++: Vektor per (const) reference

Es gibt zwei Prinzipien, wie man Vektoren (grosse Wertetabellen) übergeben kann:
1. Man will die Werte „nur“ verarbeiten. Die Tabelle bleibt gleich.
2. Man will Werte in der Tabelle ändern.

Werte nicht ändern
Wird ein Vektor per const Referenz übergeben const vector <type>& <name> , so verändert man aufgrund des Schlüsselwortes const die Einträge nicht (Bjarne 8.5.4). Anstatt per Referenz kann man die Werte auch traditionell per Pointer (per Adresse) übergeben, ebenfalls mit const.

Werte verändern (Bjarne 8.5.5)
Ist das Ziel, die Einträge zu ändern, so tut man dies z. B. so:

void init(vector <int> v){
.  //
}

————————————————————————————————————————-

Adresse erhalten

int i = 5;

// Variable für Adresse
int* adresse;

adresse = &i;      // die Adresse von i wird übergeben

Aus einer Adress-Variable einen Wert auselesen

int value_1;
value_1 = * adresse;

 

..

Unterscheidung Deklaration <-> Definition

Bjarne Stromkamph behandelt diesen Unterschied im Kapitel 8.2.

Deklaration

extern variable_b;
void function_a();

Deklarationen reservieren Namen. Sie reservieren keinen Platz. Sie sind für den Linker wichtig.
Die „bekannteste“ Deklaration ist die forward declaration von Funktioen oder das setzen von globalen Variablen.
Deklarationen kommen in ein Header-File.

In Deklarationen müssen die Parameter nicht zwingend angegeben werden. Man macht dies jedoch, damit der Code lesbarer ist (Bjarne 8.5.1).

Definition
Mit der Definition wird Speicherplatz alloziert. Die Variable erhält einen Platz.

int var_2= 5;

void function_a(){
.     //code
.     return 0;
}

 

 

statische <-> dynamische Variablen

statische Variablen

<type> <name> [<value>]

– Sie haben eine fixe Grösse
– Sie werden über den Namen aufgerufen
– Ihre Gültigkeit hängt von ihrem Definitionsort ab:
.  lokal: nur in Funktion gültig
.  global (extern): im ganzen Programm
Haben nichts mit dem Keywort static zu tun
Sie liegen im Datensegment

.   <<Statische Variablen hängen von der
.        (statischen) Programmstruktur ab.>>

dynamische Variablen
– Haben keinen fixen Namen: Es gibt keine Variablenvereinbarung (Definition)
– Können nur über den Return-Pointer der Funktion malloc() bearbeitet werden
– Sie kennen keine Funktions- oder Dateigrenzen, sondern sind überall sichtbar
– Eine dynamische Variable ist durch das Programmende oder durch die Funktion free( Variablen-Pointer) vernichtbar
– Speicherort ist der HEAP

Dynamische Speicherzuweisung C: „Allocation“

Nicht dynamisch
Definiert man eine Variable, Konstante oder ein Array mit fixer Länge char array[5] , so ist die Länge des Speicherplatzes klar und die Speicherzuweisung ist nicht dynamisch.
Nicht dynamische Speicherzuweisungen werden im STACK abgelegt.

Grund für dynamisch
Die Grösse des Arrays ändert sich während der Verarbeitung. Man kann das Array nicht auf eine fixe Grösse initialisieren.
Eine dynmische Speicherzuweisung nennt man Allozierung. Die Daten werden im HEAP abgelegt.

Vorgehen
1. Speicherplatz reservieren
Dies geschieht über die Funktion malloc().  Es ist zwingend, dass man die Anzahl Bytes nennt.  int *buffer1 = malloc(n * sizeof(data));.  N bezeichnet die Anzahl daten, data bezeichnet die Grösse eines Datenpackets.
Die Funktion sizeof( )  gibt immer die Anzahl Bytes der Variable zurück.
2. Auf dynamische Daten zugreiffen
Die Funktion malloc() gibt als Returnwert die Adresse zurück. Auf dynamische Daten kann nur über den Pointer zugegriffen werden. Ein direkter Zugriff über den Variablennamen auf die Daten ist nicht möglich. data1 = buffer1[0];
3. Speicherplatz freigebe
free(buffer1); Wird Speicherplatz nicht mehr freigegeben, so entsteht ein Memory Leak. Ohne free() verkleinert sich die Speicherkapazität des RAMs.

Speicherorte: Die „Segmente“ im RAM

Grundstruktur Datenablage
Ein ausführbares Programm (*.exe) teilt seine Daten in vier Segmente ein: *.code, *.data, *, heap und Stack.

code_data_heap code_data_heap_chinese

Codesegment
Liegt bei der tiefsten Adresse. Hier liegt der Maschinencode. Häufig liegen hier auch die Konstanten. Das Codesegment kann mit einem Schreibschutz versehen werden, also nur gelesen werden.

Datensegment
Hier liegen die initialisierten globalen Variablen sowie wenn eine lokale Variable als static definiert wurde. Sind Variablen nicht initialisiert, so liegen sie im BSS Segment.

Heap
Enthält nur dynamische Variablen, die mit malloc() zur Laufzeit generiert und wieder gelöscht werden.

Stack
Legt alle sich ändernden Daten zur Laufzeit ab und holt sie permanent wieder. Ständiges Wechseln der Daten. Deshalb braucht es einen Stack Pointer, der jeweils die aktuelle Speicherstelle weiss.
Der Stack liegt an der höchsten Adresse.
Im Stack liegen alle lokalen Variablen.