Du bist hier: Startseite > Entwicklung (C/C++) > C++ Grundlagen > Funktionen, Funktion überladen und inline Funktionen

Funktionen, Funktion überladen und inline Funktionen

Eine Funktion ist eine Ansammlung von Anweisungen, der ein Name gegeben wird und die jederzeit im Programm über diesen Namen aufgerufen und ausgeführt werden kann. Während mit den bisher kennengelernten Variablen, Operatoren und Kontrollstrukturen bereits recht leistungsfähige Programme möglich sind, können mit Funktionen Anweisungen getrennt in Pakete gelegt und Programme übersichtlicher gestaltet werden.

Um Funktionen in Programmen nutzen zu können, müssen sie erstmal definiert werden. Die Definition ist immer der erste Schritt, um eine Funktion nutzen zu können. Achte unbedingt darauf, dass du einen richtigen Namen für deine Funktion verwendest!.

In allen Beispielprogrammen hast du bereits immer eine Funktion definiert gehabt.
Die Funktion "int main(void) { ... return 0; }" ist die Funktion, mit der ein C++ Programm immer startet.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. void funktionsname(void)
  5. {
  6. std::cout << "Funktion wurde aufgerufen" << std::endl;
  7. }
  8.  
  9. int main(void)
  10. {
  11. funktionsname();
  12.  
  13. std::cin.get();
  14. return EXIT_SUCCESS;
  15. }

Eine Funktionsdefinition beginnt immer mit dem Datentyp des Rückgabewertes. Der Rückgabewert ist das Ergebnis, das die Funktion liefert. Eine Funktion muss nicht unbedingt ein Ergebnis liefern. Sie muss dann mit dem Schlüsselwort void definiert werden. void bedeutet einfach, dass die Funktion kein Ergebnis liefert. In den runden Klammern übergibt man Parameter, mit denen dann in der Funktion gearbeitet werden kann. Wenn keine Parameter übergeben werden, schreibt man in die Klammern ebenfalls einfach void rein.
Die Funktion main() muss mit dem Datentyp int für den Rückgabewert definiert werden - dies schreibt der C++-Standard vor.

Wichtig ist noch, dass die Funktion bereits definiert wurde wenn sie aufgerufen wird. Falls das nicht möglich ist, muss die Funktion eine Vorwärtsdeklaration haben. Das stellt man folgendermaßen an:

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. void funktionsname(void); // Vorwärtsdeklaration
  5.  
  6. int main(void)
  7. {
  8. funktionsname();
  9.  
  10. std::cin.get();
  11. return EXIT_SUCCESS;
  12. }
  13.  
  14. void funktionsname(void) // Spätere Funktionsdefinition
  15. {
  16. std::cout << "Funktion wurde aufgerufen" << std::endl;
  17. }
  18.  

Funktionen können Parameter übergeben werden, mit denen dann inerhalb der Funktion gearbeitet werden kann.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. int addiere(int a, int b);
  5.  
  6. int main(void)
  7. {
  8. std::cout << "Das Ergebnis der Addition ist: " << addiere(3, 8) << std::endl;
  9.  
  10. std::cin.get();
  11. return EXIT_SUCCESS;
  12. }
  13.  
  14. int addiere(int a, int b)
  15. {
  16. return (a + b);
  17. }

Ein Parameter von einer Funktion kann auch mit einem Wert vordefiniert werden. Falls beim Aufruf der Funktion der Parameter nicht übergeben wird, arbeitet die Funktion mit dem vordefiniertem Wert.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. int test(int a = 100)
  5. {
  6. return (a + 100);
  7. }
  8.  
  9. int main(void)
  10. {
  11. std::cout << test() << std::endl; // 100+100 = 200
  12. std::cout << test(400) << std::endl; // 400+100 = 500
  13.  
  14. std::cin.get();
  15. return EXIT_SUCCESS;
  16. }

C++ bietet den Luxus, dass Funktion überladen werden können. Das bedeutet, dass es durchaus mehrere Funktionen geben kann, die den gleichen Namen haben jedoch an den übergebenen Parametern unterschieden werden können. Der Compiler verbindet die zu den Aufrufparametern passende Funktion mit den Aufruf automatisch.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. int addiere(int a, int b);
  5. float addiere(float a, float b);
  6.  
  7. int main(void)
  8. {
  9. std::cout << "Das Ergebnis der Addition ist: " << addiere(3, 8) << std::endl;
  10. std::cout << "Das Ergebnis der Addition ist: " << addiere(3.3357f, 8.7577f) << std::endl;
  11.  
  12. std::cin.get();
  13. return EXIT_SUCCESS;
  14. }
  15.  
  16. int addiere(int a, int b)
  17. {
  18. return (a + b);
  19. }
  20.  
  21. float addiere(float a, float b)
  22. {
  23. return (a + b);
  24. }

Das f hinter 3.3357 und 8.7577 bedeutet, dass die übergebenen Werte denn Datentyp float (Gleitkommazahlen) haben!

Der Aufruf einer Funktion benötigt eine gewisse Zeit. Die Rücksprungadresse wird auf den Stack gelegt. Die Parameter werden ebenfalls auf den Stack gelegt. Die Funktion wird angesprungen. Die Parameter werden nach dem Ablauf der Funktion wieder freigegeben, und das Programm springt zum Ausgangspunkt zurück. Auch wenn sich dies alles langwierig anhört, benötigt der Aufruf einer Funktion nur einen geringen Teil der Laufzeit eines Programms und fällt normalerweise nicht ins Gewicht. In zeitkritischen Anwendungen aber kann der Aufruf einer Funktion bereits zu viel Zeit in Anspruch nehmen. Um dies zu vermeiden, kann einer Funktion das Attribut inline vorangestellt werden. Hier wird der Compiler die Anweisungen nicht als Funktion aufrufen, sondern an die Stelle des Funktionsaufrufs jeweils den Funktionsinhalt kopieren. Stellt der Compiler fest, dass eine solche Ersetzung keine Laufzeitvorteile bringt, steht es ihm frei, die Inline-Funktion so zu übersetzen, dass sie wie jede andere Funktion aufgerufen wird.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. inline int addiere(int a, int b);
  5.  
  6. int main(void)
  7. {
  8. std::cout << "Das Ergebnis der Addition ist: " << addiere(3, 8) << std::endl;
  9.  
  10. std::cin.get();
  11. return EXIT_SUCCESS;
  12. }
  13.  
  14. inline int addiere(int a, int b)
  15. {
  16. return (a + b);
  17. }

Im Beispiel wird die Minimum-Funktion nicht als Funktion ausgeführt, sondern in der Form, dass der Code der Funktion direkt an der Aufrufstelle eingefügt wird. Dadurch wird der Sprung zur Funktion gespart, sowie das Kopieren der Parameter auf den Stack und den Rücksprung. Der übersetzte Code würde also so aussehen, als würde er direkt an der Aufrufstelle stehen.

Datei:  Quelldateien/main.cpp
  1. #include <iostream> // std::cout, std::endl, std::cin
  2. #include <stdlib.h> // EXIT_SUCCESS
  3.  
  4. int main(void)
  5. {
  6. std::cout << "Das Ergebnis der Addition ist: " << (3 + 8) << std::endl;
  7.  
  8. std::cin.get();
  9. return EXIT_SUCCESS;
  10. }

Bei einer Inline-Funktion hat man sämtliche Vorteile einer Funktion und gewinnt Geschwindigkeitsvorteile hinzu. Der Ersetzungsmechanismus vergrößert natürlich das Programm. Wenn die Funktion aber nicht besonders groß ist, fällt das nicht ins Gewicht.

Wird innerhalb eines Funktionsblocks eine Variable definiert, spricht man von einer lokalen Variablen. Außerhalb der Funktion kann nicht auf diese Variable zugegriffen werden. Sie wird erzeugt und initialisiert, wenn die Definition ausgeführt wird. Sie wird freigegeben, wenn der Block, in dem sie definiert ist, verlassen wird.

Kommentare zu diesem Beitrag

Sie müssen angemeldet sein, um eine Nachricht zu erstellen. Anmelden »