Zusammenfassung
Bisher war jedes Programm des Kurses ein einziger Block, main, in dem alles dort geschrieben wird, wo es gebraucht wird. Diese Lektion lehrt, einem Teil eines Programms einen Namen zu geben und ihn zu benutzen, ohne in sein Inneres zu schauen: die Funktion. Behandelt werden die Deklaration, die dem Compiler den Namen, den Rückgabetyp und die Parameter ankündigt; die Definition, die den Rumpf hinzufügt; und der Aufruf, der die Kontrolle an diesen Rumpf übergibt und den zurückgegebenen Wert empfängt. Unterschieden wird, was der Compiler beim Kompilieren prüft (dass jeder Aufruf zu einer Deklaration passt), von dem, was bei der Ausführung geschieht (der Sprung zur Definition und die Rückkehr). Erklärt wird, warum es undefiniertes Verhalten ist, das Ende einer Funktion, die einen Wert zurückgeben muss, ohne ein return zu erreichen. Die Ausführung wird mit dem Aufrufstapel verfolgt, der für jeden laufenden Aufruf einen Stapelrahmen aufbewahrt. Und jede Funktion wird durch einen Vertrag spezifiziert, ihre Vorbedingung und ihre Nachbedingung, der sagt, was die Funktion vom Aufrufer verlangt und was sie im Gegenzug garantiert.
Lernziele
- Funktionen mit Parametern und Rückgabewert deklarieren, definieren und aufrufen und in einem Programm angeben, welcher Teil die Deklaration und welcher die Definition ist.
- Mit einem Diagramm des Aufrufstapels die Ausführung eines Programms verfolgen, dessen Funktionen einander aufrufen.
- Eine Funktion durch ihre Vorbedingung und ihre Nachbedingung spezifizieren und einen Aufruf schreiben, der die Vorbedingung verletzt.
- Erklären, warum eine Funktion, die auf einem Pfad keinen Wert zurückgibt, undefiniertes Verhalten ist, und die zugehörige Warnung des Compilers erkennen.
Warum Funktionen
Die Programme der vorigen Einheit lösten jedes Problem innerhalb von main, und das genügte, solange die Probleme klein waren. Sobald ein Programm aber wächst, treten drei Schwierigkeiten auf. Die erste ist die Wiederholung: Wird dieselbe Berechnung an drei Stellen gebraucht, so schreibt man sie dreimal, und ein Fehler darin wird dreimal korrigiert (oder man vergisst, ihn an einer Stelle zu korrigieren). Die zweite ist das Lesen: Ein Block von fünfzig Zeilen sagt nicht, was er tut, sondern wie er es tut, und der Leser muss die Absicht aus dem Mechanismus rekonstruieren. Die dritte ist das Testen: Ist alles vermischt, so gibt es keine Möglichkeit, einen Teil zu prüfen, ohne den Rest auszuführen.
Eine Funktion ist ein benanntes Programmstück, das Daten empfängt, die Parameter heißen, und ein Ergebnis liefert, das Rückgabewert heißt. Die Mathematik kennt die Idee seit Jahrhunderten: Der Abstand zweier Punkte der Ebene ist eine Funktion ihrer vier Koordinaten, , und wer den Umfang eines Dreiecks berechnet, wiederholt die Formel nicht dreimal, sondern benennt sie und wendet sie dreimal an. In C++ schreibt man dasselbe.
Das Programm liest die Koordinaten der drei Ecken eines Dreiecks ein und gibt seinen Umfang aus, also die Summe der Längen seiner drei Seiten.
#include <cmath>#include <iostream>#include <print>// Abstand zwischen den Punkten (x1, y1) und (x2, y2).double distance(double x1, double y1, double x2, double y2){ const double dx{x2 - x1}; const double dy{y2 - y1}; return std::sqrt(dx * dx + dy * dy);}int main(){ double ax{}; double ay{}; double bx{}; double by{}; double cx{}; double cy{}; std::cin >> ax >> ay >> bx >> by >> cx >> cy; const double perimeter{distance(ax, ay, bx, by) + distance(bx, by, cx, cy) + distance(cx, cy, ax, ay)}; std::println("Umfang: {}", perimeter);}0 0 3 0 0 4Umfang: 12Die Seiten des Dreiecks mit den Ecken , und messen 3, 5 und 4, und ihre Summe ist 12.
Die Funktion distance wird einmal geschrieben und dreimal benutzt; main liest sich wie die Definition des Umfangs, „die Summe dreier Abstände“; und distance lässt sich für sich allein testen, mit einem Punktepaar, dessen Abstand man kennt. So gewinnt man die drei Dinge, die fehlten. Die allgemeine Lehre, die in jeder Sprache gilt, lautet: Eine Funktion benennt eine Idee; wer sie benutzt, denkt daran, was sie tut, nicht daran, wie sie es tut. Diese Trennung zwischen Gebrauch und Umsetzung heißt prozedurale Abstraktion, und sie ist das Thema der ganzen Einheit.
Inhalt wird geladen…
Abgeschlossen
Melde dich an, um deinen Fortschritt zu speichern