Bisher haben wir all unseren Programmcode in die main()-Funktion geschrieben. Wenn man nur kleine Programme oder Beispiele schreibt, kann das durchaus Sinn machen. Wenn ein Programm aber größer und komplexer wird, sollte man den Code strukturieren. Dabei helfen Funktionen.

Funktionen helfen dabei ein Programm in logische Blöcke zu unterteilen, die man dann aufrufen kann, wenn man sie benötigt. Eine Funktion ist quasi ein Unterprogramm, dem man Parameter übergeben kann und die etwas zurückgeben kann. Damit sie ihre Arbeit verrichtet, muss sie aufgerufen werden.

Ein klassisches Beispiel für eine Anwendung ist die Berechnung des Umfangs und der Fläche eines Kreises. Der Nutzer gibt einen Radius an und das Programm berechnet diese beiden Werte. Man könnte das nun alles in die main()-Funktion schreiben. Eine bessere Lösung wäre es, wenn man den Code in logische Blöcke unterteilt: Eine Funktion, die den Umfang berechnet und eine Funktion, die die Fläche des Kreises bestimmt.

// circle01.cpp

#include <iostream>

using namespace std;

const double PI = 3.14159265;

// Function declarations (prototypes)
double area(double);
double circumference(double);

int main() {
    cout << "Enter radius: ";
    double radius = 0;
    cin >> radius;

    // Call function area()
    cout << "Area is: " << area(radius) << endl;

    // Call function circumference()
    cout << "Circumference is: " 
         << circumference(radius) << endl;
    
    return 0;
}

// Function definitios (implementations)
double area(double radius) {
    return PI * radius * radius;
}

double circumference(double radius) {
    return 2 * PI * radius;
}
Enter radius: 4
Area is: 50.2655
Circumference is: 25.1327

In diesem Fall ist main() – welches natürlich auch eine Funktion ist – kurz und delegiert die Berechnungen an die Funktionen area() und circumference(). Das Programm demonstriert sehr anschaulich folgende Dinge, die nötig sind, wenn man Funktionen nutzt:

  • Die Funktionsprototypen werden vor main() deklariert, damit sie dort auch bekannt sind.
  • Die beiden Funktionen area() und circumference() werden in main() aufgerufen.
  • Die beiden Funktionen area() und circumference() werden außerhalb von main() definiert.

Was genau ist denn ein Funktions-Prototyp?

double area(double);
double circumference(double);

Das erste double ist jeweils der Rückgabewert. D.h. die Funktion gibt als Ergebnis in diesen beiden Fälle eine double Zahl zurück. Danach folgt der Name der Funktion und in den Klammern ist die Parameterliste. Die Parameterliste des Prototyps muss die Parameter nicht benennen, d.h. es reicht wenn der Typ der Parameter angegeben wird. Man könnte hier aber auch einen Namen angeben.

Wenn man keinen Prototyp deklariert, würde der Aufruf der Funktionen innerhalb von main() einen Fehler verursachen, weil die Funktionen einfach nicht bekannt wären. Die Prototypen sagen dem Compiler, dass es sich hierbei um zwei Funktionen handelt.

Eine Funktion kann mehrere Parameter besitzen, aber nur einen Rückgabewert! Falls man keinen Rückgabewert benötigt, wird dieser mit void angegeben.

Was ist die Definition einer Funktion?

Die eigentliche Funktion – die Implementation also – nennt man die Definition einer Funktion.

double area(double radius) {
    return PI * radius * radius;
}

Ein return Ausdruck ist notwendig, außer die Funktion hat den Rückgabewert void. In diesem Fall benötigt der Körper der Funktion area() einen return Ausdruck, weil die Funktion ein double zurückgeben soll.

Wie man im Beispiel sieht, besteht die Definition immer aus einem Funktionskopf und einem Funktionskörper. Im Kopf wird der Name, der Datentyp, der zurückgegeben wird und die Parameterliste angegeben. Im Funktionskörper wird definiert, was die Funktion eigentlich macht bzw. wie sie es macht.

Das nächste Beispiel zeigt die Definition einer Funktion, die die größere von zwei Zahlen zurückgibt.

// larger.cpp

int larger(int first, int second) {
    int temp;
    if (first > second) {
        temp = first;
    }
    else {
        temp = second;
    }

    return temp;
}

Der Rückgabetyp ist ein Integer int. Es gibt zwei Parameter, die jeweils ebenfalls ein int sind. Die Deklaration oder der Prototyp dieser Funktion sieht folgendermaßen aus:

// with the names of the parameters:
int larger(int first, int second);  
// without the names of the parameters:
int larger(int, int);                        

Funktionsaufruf

Ein Funktionsaufruf …. ja, er ruft eine Funktion auf, damit sie ihren Job erledigt. Das folgende Beispiel zeigt, wie wir die larger() Funktion von eben innerhalb einer main() Funktion aufrufen können:

int main() {
    cout << larger(3,13) << endl;
    cout << larger(10,12) << endl;
    cout << larger(2,12) << endl;
    return 0;
}

Argumente und Parameter

Ein Parameter ist eine Variable, die im Kopf der Funktion deklariert wird. Ein Argument ist ein Wert, der einen Parameter initialisiert, sobald die Funktion aufgerufen wird. Ein Parameter ist also wie eine Variable auf der linken Seite eines Zuweisungsausdrucks. Das Argument ist dementsprechend der Wert auf der rechten Seite dieses Zuweisungsausdrucks. Die Initialisierung erfolgt erst, wenn die Funktion explizit aufgerufen wird.