Eine Funktion kann natürlich auch mehrere Eingabewerte verlangen; die werden dann einfach hintereinander geschrieben, etwa so:

int mul( int x, int y ) { return x * y; }

Der Aufruf erfolgt dann ganz simpel per

mul( 42, 2 )

Worauf man übrigens achten muss: wurde eine Variable bereits als Funktionsparameter deklariert, kann im Rumpf der Funktion keine Variable mit dem gleichen Namen deklariert werden. Der folgende Code ist also ungültig (unabhängig von seiner Sinnhaftigkeit):

int f( int x ) { int x = 1; return x * x; }

Ein letztes Konzept noch: bei manchen Funktionsaufrufen möchte man es sich manchmal ersparen, bestimmte Argumente immer mit angeben zu müssen, da sie sowieso meist (nicht immer!) den gleichen Wert haben sollen. In diesem Fall kommen dann die sogenannten Default-Argumente zum Einsatz. Bei der Deklaration eines Funktionsparameters kann ihm ein Standard- oder Default-Wert zugewiesen werden; wann immer beim Funktionsaufruf kein Argument für diesen Parameter übergeben wird, wird stattdessen automatisch der Default-Wert eingesetzt. Das sieht dann so aus:

int f( int x, int y = 1 ) { return x * y; }

Aufgerufen werden kann diese Funktion sowohl per f( 42, 2 ) als auch per f( 42 ) – im ersten Fall wäre das Ergebnis 84, im zweiten 42; natürlich kann auch mehr als ein Parameter mit Default-Argumenten versehen werden. Um bei einem Funktionsaufruf zu wissen, wann Default-Argumente eingesetzt werden müssen, dürfen diese natürlich nur am Ende der Parameterliste stehen, da sonst nicht klar wäre, wie die Funktion aufgerufen werden soll. Nehmen wir einmal den folgenden Funktionskopf (welches so ungültiger Code ist):

int f( int x = 1, int y, int z = 3 )

und dazu den folgenden Aufruf der Funktion:

f( 42, 84 )

Würde eine beliebige Anordnung der Default-Argumente erlaubt sein, wäre nun gar nicht klar, wie f aufgerufen werden soll. Es könnte die 42 für x und die 84 für y oder die 42 für y und die 84 für z eingesetzt werden. Aus diesem Grund ist das auch gar nicht erst erlaubt und Default-Argumente müssen immer am Ende der Parameterliste stehen.

1 / 2

Kommentare (21)

  1. #1 MartinB
    April 16, 2013

    …wobei es ja wirklich schade ist, dass C++ keinen Aufruf der Art f(x=7, y=a) erlaubt

  2. #2 Marcus Frenkel
    April 16, 2013

    Darüber kann man trefflich streiten. Auf der einen Seite hätte ich mir das auch an der ein oder anderen Stelle gewünscht, weil man sonst (insbesondere bei Konstruktoren) zu abenteuerlichen Parameterlisten und Überladungen genötigt wird.

    Auf der anderen Seite ist diese Art der Notation für ein intuitives Verständnis von Programmcode nicht unbedingt förderlich, da immer erst die Parameterreihenfolge herausgefunden werden muss.

    Zwei weitere Punkte kommen hinzu:

    1.: Was soll man als Basis für die Parameternamen verwenden – die Funktionsdeklaration oder die Funktionsdefinition? Die Parameternamen können bei beiden voneinander abweichen. Noch schlimmer: in der Deklaration muss man gar keinen Namen angeben; die Deklaration würde aber als Basis für den Aufruf herangezogen werden (man kann auch Default-Argumente für namenlose Parameter angeben), so dass hier ein Namensproblem besteht.

    2.: f( x=7, y=a) ist ein gültiger Aufruf einer Funktion f, wenn im Aufruf-Scope die Variablen x und y vorhanden sind; Zuweisungen sind in C++ keine Anweisungen, sondern Ausdrücke mit dem Wert der rechten Seite der Zuweisung – rein syntaktisch ginge das also schon gar nicht.

  3. #3 MartinB
    April 16, 2013

    @marcus
    ” Die Parameternamen können bei beiden voneinander abweichen.”
    Ja, das ist eine der relativ sinnlosen Freiheiten von C++ – oder ist das zu irgendwas gut?

    “Auf der anderen Seite ist diese Art der Notation für ein intuitives Verständnis von Programmcode nicht unbedingt förderlich, da immer erst die Parameterreihenfolge herausgefunden werden muss.”
    ?? Das ist doch gerade der Fall, wenn ich nicht (x=a) im Argument schreiben darf.

    “Zuweisungen sind in C++ keine Anweisungen”
    Aber das müsste ja nicht zwingend so sein, niemand würde es prinzipiell verbieten, die Syntax entsprechend zu ändern oder eine spezielle Sytax wie
    x:=a
    einzuführen. (Sonst baut C++ ja auch für alles einen Spezialfall.)

  4. #4 Marcus Frenkel
    April 16, 2013

    @MartinB

    ”Die Parameternamen können bei beiden voneinander abweichen.”

    Ja, das ist eine der relativ sinnlosen Freiheiten von C++ – oder ist das zu irgendwas gut?

    Die ursprüngliche Intention dahinter kenne ich nicht; technisch ist das dadurch bedingt, dass bei der Zuordnung von Deklaration und Definition lediglich die Signatur eine Rolle spielt und der Variablenname technisch gesehen nicht zur Signatur gehört. Dadurch können beide voneinander abweichen.

    “Auf der anderen Seite ist diese Art der Notation für ein intuitives Verständnis von Programmcode nicht unbedingt förderlich, da immer erst die Parameterreihenfolge herausgefunden werden muss.”

    ?? Das ist doch gerade der Fall, wenn ich nicht (x=a) im Argument schreiben darf.

    Die Reihenfolge ist in C++ immer klar, wenn man die Deklaration der Funktion kennt, nämlich von vorne nach hinten minus eventuell einige Default-Argumente – die aber auch streng von hinten an gezählt. Durch Änderung der Reihenfolge der Argumente reicht ein einfacher Blick bei bekannten Funktionen nicht mehr, wenn man sich z.B. nur für das erste Argument interessiert (insbesondere beim Debuggen von Code) – man muss erst schauen, an welcher Stelle das “erste” nun steht.

    “Zuweisungen sind in C++ keine Anweisungen”

    Aber das müsste ja nicht zwingend so sein, niemand würde es prinzipiell verbieten, die Syntax entsprechend zu ändern oder eine spezielle Sytax wie
    x:=a einzuführen. (Sonst baut C++ ja auch für alles einen Spezialfall.)

    Syntaxänderungen gehen nicht, das macht kaum eine Sprache. Wenn die Syntax einmal ist, wie sie ist, bleibt sie so. Eine Syntaxerweiterung wäre natürlich eine Möglichkeit, wenngleich auch das Komitee zur Erweiterung von C++ davor glaube ich eher zurückschreckt, da jede Syntaxerweiterung die Sprache komplexer macht. Aktuell ist, soweit ich weiß, auch kein Vorschlag zur Angabe der Argumentpositionen in Bearbeitung.

  5. #5 MartinB
    April 16, 2013

    Anscheinend gibt es die Möglichkeit bei boost – benutzt habe ich das bisher aber noch nicht:
    https://www.boost.org/doc/libs/1_37_0/libs/parameter/doc/html/index.html

    Und nein, ändern kann und sollte man den Standard jetzt nicht mehr (es gibt bestimmt irgendwelche programmierer, die so geschichten wie x=a im Aufruf einer Funktion schreiben, um gleich noch irgendwo was zuzuweisen…)

  6. #6 Marcus Frenkel
    April 16, 2013

    Ach je, Boost-Magie. Ich vergaß. Boost kann ja alles.
    Das sieht fürchterlich kompliziert in der Nutzung aus, aber gut zu wissen, dass es so etwas gibt. Vielleicht braucht man es ja doch einmal.

  7. #7 Nestiii
    April 16, 2013

    Noch kein Wort zu Wert- vs. Referenztyp Parametern und Variablen? Wahrscheinlich auch besser, nicht gleich alle mit Pointern abschrecken, oder? Noch ein Tipp an alle: Beim Programmieren mit C++ am besten den Speicherplatz im Hirn “const” deklarieren, sonst wird er möglicherweise später von neuen Wissen (Programmiersprachen) unbeabsichtigt überschrieben 😉

  8. #8 Marcus Frenkel
    April 16, 2013

    @Nestiii
    Kommt noch, kommt noch. Eins nach dem anderen.

  9. #9 t
    April 16, 2013

    Hallo !
    Ich hab eine Anregung:
    Stell am Ende der Serie eine Versionsverwaltung vor. Programmieren ist kein Vergnügen für Solisten. Da sind viele Menschen beteiligt.
    Gibt es da Systeme die ähnlich wie Wikipedia arbeiten ?

  10. #10 Marcus Frenkel
    April 16, 2013

    Gibt es da Systeme die ähnlich wie Wikipedia arbeiten ?

    Das verstehe ich nicht ganz. Es gibt Systeme für Versionsverwaltung von Quelltext (SVN und Git, um nur mal 2 verbreitete zu nennen) – mit Wikipedia haben die allerdings weniger zu tun.

  11. #11 rolak
    April 16, 2013

    Zu MartinBs benannten Parametern: Da braucht es keine magischen UniversalProblemSolver-Sprachen, das ist mir schon ziemlich oft untergekommen – auf die Schnelle im www gefunden habe ich allerdings nur VBA.

    Zu der return(42)-Funktion gibt es ja eigentlich den Klassiker:

    int random()
    {
      return 3;
      //proofed beeing random by throwing a dice//
    }

  12. #12 Marcus Frenkel
    April 16, 2013

    @rolak

    Zu MartinBs benannten Parametern: Da braucht es keine magischen UniversalProblemSolver-Sprachen, das ist mir schon ziemlich oft untergekommen – auf die Schnelle im www gefunden habe ich allerdings nur VBA.

    C#. 😉

  13. #13 rolak
    April 16, 2013

    C#

    Da siehste mal, Marcus, aus dem c*-Raum bin ich bisher nur mit c und c++ zwangskontaktiert worden.

    Ist ja auch *räusper* erst seit c# 4.0 ;-), wie ich gerade lese, denn ich habe doch noch den Stein der WeisenSprachen gefunden. Lisp, Python, Fortran durfte ich schon ausgiebig…

  14. #14 Doomtrain
    April 16, 2013

    C# 4.0 ist mir auch neu (ich halte mich an die 3.0 spezifikation, ist ja nur ne Erweiterung, keine Änderung ;)).

    Prinzipiell kann mal allerdings sagen, dass man in C# so ziehmlich alles machen kann, was einem einfällt (So krank es auch sein mag). Einiges ist aber auch sehr praktsich. Mir Fallen da gleich ein paar Beispiele ein, die passen nur nicht ganz zum Thema.

  15. #15 Stefan W.
    https://demystifikation.wordpress.com
    April 16, 2013

    Man kann im Funktionsrumpf sehr wohl einen Parameter verdecken, nur nicht unmittelbar.

    Eine gute Idee ist das freilich selten, weil es die Chance der Verwirrung erhöht:

    #include
    using namespace std;
    int f (int x)
    {
    int p = 0;
    for (int a = 0; a < x; ++a) {
    int x = a;
    p += a * 2;
    }
    return p;
    }
    int main (void) {
    cout << "f (3)" << f (3) << "\n";
    }

    Auch ist die Information, dass es sich um C++ handelt, im Artikel gut versteckt. Ich fand es nur in der Tagliste unten. Das #include ist noch verräterrisch – ansonsten könnte das meiste auch Java, Javascript, C und PHP sein.

    Scala hat benannte Parameter und Defaultargumente. Solange man die Parameter bei der Übergabe nicht benennt gilt auch die Von-links-nach-rechts-Auflösung.

    Allerdings kann man bei Scala multiple Parameterlisten verwenden und dann in jeder mit default-Parametern von rechts beginnen.


    def ruggediguh (ist: Int = 4, im: Int = 3) (blut:Int) (schuh: String="Ballettschuh") {
    /** some implementation*/
    }

    ruggediguh (2, 1) (b) ("foo")
    ruggediguh (im=9) (b) ()
    ruggediguh () (b) ()
    ruggediguh () (b) ()

    Allerdings hat diese Beispielfunktion kein Ergebnis, weil es nicht nötig ist um das Verhalten zu zeigen und ist daher besser als Prozedur bezeichnet.

  16. #16 Marcus Frenkel
    April 16, 2013

    @Stefan W.

    Man kann im Funktionsrumpf sehr wohl einen Parameter verdecken, nur nicht unmittelbar.

    Das weiß ich…bei geschachtelten Blöcken sind wir in der Serie aber noch nicht…

    Auch ist die Information, dass es sich um C++ handelt, im Artikel gut versteckt.

    Siehe den ersten Artikel der Serie…

  17. #17 Dr. Webbaer
    April 17, 2013

    Funktionsparameter bezeichnen einen explizit adressierten Scope oder Geltungsbereich innerhalb des Rechenapparats, der “extra” oder implizit bereitgestellt wird, es geht hier letztlich um die Verwaltung der Logik, um das Schaffen von Einheiten im Sinne von Divide et impera.

    Es gibt auch Funktionen oder F.-Parametriesierung außerhalb der Programmiererei, es gibt sozusagen für das Erkenntnissubjekt ein entsprechendes Logikbedürfnis, gerade auch die Verteilung entsprechend.

    MFG
    Dr. W

  18. #18 DeLuRo
    April 17, 2013

    @Druide Webbaer: Und was soll jetzt das Geschwafel?

    Das bringt niemanden weiter. Zuerst konzentriere man sich auf das, was da ist, und das, was damit getan werden muss — sonst hängt man sich an endlosen Denkschleifen auf. Es gibt Variablen, es gibt Funktionen mit oder ohne Parametern bzw. Argumenten, die kann man auch als Variablen betrachten, alles hat irgend einen Typ, alles hat Namen, und fertig.

    Selbstverständlich ist alles in Einheiten (Einzel- / Unter-Elemente) eingeteilt, und es geht immer darum, die mit den Werkzeugen verbundene Selbstverwaltung zu bewältigen.

  19. #19 Dr. Webbaer
    April 18, 2013

    DeLuRo, der lustige Roboter, man hätte hier gleich ein wenig vorbauen können Richtung OOP.
    Programmieren benötigt die Philosophie.

    MFG
    Dr. W

  20. #20 DeLuRo (Der Lustige Robot'--)
    April 19, 2013

    Man sollte vor allem nicht mit zu vielen Dingen gleichzeitig beginnen, sondern sortiert und anschaulich bleiben. Objekt-Orientierte Programmierung (OOP) ist ein komplexeres und höher angesiedeltes Paradigma, das kann später kommen. Und natürlich ist die Didaktik seiner Texte allein Sache von Marcus Frenkel.

    Einzig wichtig scheint mir der Hinweis auf die Vielschichtigkeit von “Programmieren” und die Abstraktionslevel zu sein: man kann auf Prozessorebene mit Maschinencode oder Assembler arbeiten, oder mit abstrahierten prozeduralen “Statements”, oder auch noch höher mit funktionalen oder objektorientierten Konstrukten. Letztlich bewirken dann Spezialsprachen wie solche zur Datenbankabfrage den Abruf noch komplexerer Semantiken.

    ­
    Programmieren ist Handwerk und benötigt daher zuerst keine Philosophie, sondern eine solide Ausbildung mit guten Standbeinen. — Philosophie ist außer für Berufsphilosophen etwas für Politiker, die anders keine Argumente finden, oder für Arbeitslose, die gerade nichts zu tun haben.

    Programmierer sind noch keine Informatiker, und tatsächlich kann man mit Produkten der Programmierung und weiteren Organisationsergebnissen größere schaffende “schöpfende” Tätigkeiten aufbauen. Informatiker sind gleichzeitig und in einer Person –gesprochen in Analogie zum Gebäudebau– Architekten, Bauingenieure, Projektplaner, Gewerkeleiter und (als Programmierer) Baufachgesellen und Hilfsarbeiter — und manchmal sogar die eigenen Finanziers.

    ­
    Trotzdem solltem man immer mit dem Anfang anfangen — den handwerklichen und fachlichen Grundlagen.

  21. #21 Dr. Webbaer
    April 19, 2013

    Trotzdem solltem man immer mit dem Anfang anfangen — den handwerklichen und fachlichen Grundlagen.

    Das klingt solid, lustiger Roboter, oder halbwegs lustiger Roboter.

    Und so wie die Beschaffenheit der Texte dem hiesigen Inhaltegeber obliegt, obliegt das Feedback in der Regel dem jeweiligen Geber, was Ihnen vielleicht entgangen ist.

    Und der findet halt, dass -auch um sich von der x-beliebigen Schilderung abzugrenzen- eine programmier-philosophische Ausrichtung nicht unhilfreich wäre.

    Programmieren ist Handwerk und benötigt daher zuerst keine Philosophie, sondern eine solide Ausbildung mit guten Standbeinen. — Philosophie ist außer für Berufsphilosophen etwas für Politiker, die anders keine Argumente finden, oder für Arbeitslose, die gerade nichts zu tun haben.

    Wobei zu diesem Handwerk bspw. die COBOL-Programmierer, die sich vor mehreren Jahrzehnten noch mit sozusagen nackten Dateien und selbst gebastelter Indizierung quälten, sozusagen philosophisch die indexorientierten Dateien anforderten und nach den ISAMs die RDBMSe, das SQL. Weil man mit den Datentabellen ja immer sehr ähnliches tat.

    Ähnlich ist auch OOP entstanden. Der Schreiber dieser Zeilen kennt noch Code, der sozusagen objektorientiert oder am Geschäftsobjekt orientiert war, als es OOP noch nicht gab.

    MFG
    Dr. W (der Ihre hiesigen kommentarischen Nachrichten ein wenig lasch findet)