"Funktion akzeptiert keine 2 Argumente" (Solved)



  • Huhu,

    dein Prototyp passt mit der Defintion nicht zusammen:

    int addition ( int, int ) ;
    

    Du hast aber:

    int addition ( int ) ;
    

    geschrieben.

    Außerdem: Gewöhn dir einen schönen Stil an: Schreib deine Prototypen immer in einer eigenen Zeile.



  • ist das addition(int) in der Zeile 11 nicht einfach überflüssig?



  • Kasimir87 schrieb:

    ist das addition(int) in der Zeile 11 nicht einfach überflüssig?

    Ne, wenn man die Definition nach 'main' schreibt muss man mind. einen Prototypen angeben, damit das Hauptprogramm weiß, dass es so eine Funktion überhaupt gibt.

    Er könnte sich den Prototypen sparen, wenn er die Definition vor 'main' schreibt --> ABER! --> Schlechter Stil.

    Hoffe habe dich nicht falsch verstanden. :xmas1:



  • Nein. Der Compiler arbeitet z.T. kontextsensitiv, d.h., er sucht das Wort/Symbol "addition", was aber erst unter dem ersten Auftreten definiert wird. Woher soll er also beim Aufruf wissen, was das ist? Oder aber, angenommen, die Funktion wird vor der main() definiert. Was wäre, wenn die Funktion einfach nie aufgerufen werden würde? Der Code würde vom Compiler (mal abgesehen von Optimierung) trotzdem erzeugt werden, obwohl er nicht benutzt wird. Deshalb wird zwischen Definition und Deklaration getrennt, es gibt aber auch viele andere Gründe, z.B. Schnittstellen und Modularität. :xmas1:

    Siehe u.a.: "Die C++ Programmiersprache, Kapitel 9 Quelldateien und Programme"



  • Huch Ad aCTa,

    das wusste ich jetzt nicht! 😮
    Sollte mir das Kapitel nochmal durchlesen, danke für die Erklärung.



  • Jo, das war der Grund, ist gelöst, vielen Dank!

    Übrigens, deine Kommentare im Code sind ausnahmslos sinnlos.

    Liegt am Tutor - Schon in der letzten KA mussten wir alles totkommentieren. Dann kann ich das jetzt auch schon für die Vorbereitung auf die morgige Arbeit tun...



  • Sunny31 schrieb:

    Kasimir87 schrieb:

    ist das addition(int) in der Zeile 11 nicht einfach überflüssig?

    Ne, wenn man die Definition nach 'main' schreibt muss man mind. einen Prototypen angeben, damit das Hauptprogramm weiß, dass es so eine Funktion überhaupt gibt.

    Er könnte sich den Prototypen sparen, wenn er die Definition vor 'main' schreibt --> ABER! --> Schlechter Stil.

    Hoffe habe dich nicht falsch verstanden. :xmas1:

    ah gut. also das mans nicht braucht wenn man die definition davor schreibt wusste ich nur halb. ich ging davon aus, dass ein prototyp in dem falle einfach unnötig ist. und wusste nicht, dass es einen unterschied macht ob ich vor oder nach main die definition schreibe. und ich wusste nicht, dass es schlechter stil ist wenn man die definition davor schreibt. warum ist denn das so?



  • In Minimalbeispielen (ließ "in einer einzigen Datei/Übersetzungseinheit") wäre die Begründung nie so richtig offensichtlich. 🙂
    Du zerdommernst dir entweder die Modularität oder erzeugst große Kompilierungsabhängigkeiten. Merk' dir einfach:
    Forward-Deklarationen von Klassen und Deklarationen von Funktionen in eine Headerdatei

    Definitionen von Klassen und Deklarationen von Funktionen in eine Headerdatei

    Definitionen von Klassenmembern bzw. Definitionen von Funktionen in eine Quellcodedatei

    Wenn du die Funktionsdefinitionen auf Gedeih und verderb davor (also in eine Headerdatei) und nicht dahinter (in eine andere Kompilier-Einheit) stellst, wird der Linker sie immer mit in den Binärcode der ausführbaren Datei schreiben, egal ob du sie benutzt oder nicht. Wenn du hingegen nur die Schnittstelle ( = Deklaration) zur Verfügung stellst, wird er Compiler den Code in der Übersetzungseinheit akzeptieren und der Linker wird den benötigten Objektcode dann nach dem Kompilieren hinzufügen, ganz im C++-Sinn: "You only pay for what you use."



  • wie stell ich denn etwas in eine andere Kompilier-Einheit?
    Ich kenn das nur mit header-dateien O.o



  • sunny31 schrieb:

    Er könnte sich den Prototypen sparen, wenn er die Definition vor 'main' schreibt --> ABER! --> Schlechter Stil.

    Naja, das ist Geschmackssache. Bei grösseren Projekten ist es wohl eher schlechter Stil, in Main.cpp überhaupt etwas anderes als main() und #include -Direktiven zu haben.

    Ad aCTa schrieb:

    Wenn du die Funktionsdefinitionen auf Gedeih und verderb davor (also in eine Headerdatei) und nicht dahinter (in eine andere Kompilier-Einheit) stellst, wird der Linker sie immer mit in den Binärcode der ausführbaren Datei schreiben, egal ob du sie benutzt oder nicht.

    So sicher wäre ich mir da nicht, da müsste ja die halbe Standardbibliothek ständig mitgelinkt werden. Moderne Compiler wie der von MSVC++ sind sogar fähig, beim Linken noch über Inline-Optimierungen zu entscheiden, dann können sie wohl auch unnötige Symbole weglassen.

    Kasimir87 schrieb:

    wie stell ich denn etwas in eine andere Kompilier-Einheit?
    Ich kenn das nur mit header-dateien O.o

    So:

    // Foo.hpp - Schnittstelle mit Deklaration
    void Foo();
    
    // Foo.cpp - Implementierung mit Definition
    #include "Foo.hpp"
    void Foo()
    {
        // ...
    }
    
    // Main.cpp - Benutzung von Foo()
    #include "Foo.hpp"
    int main()
    {
        Foo();
    }
    

    Unter dem Kapitel "Modulare Programmierung" deines C++-Buchs nachzuschlagen. :xmas1:



  • So sicher wäre ich mir da nicht, da müsste ja die halbe Standardbibliothek ständig mitgelinkt werden.

    Wieso? Ich schätze, fast alles in der Standardbibliothek sind Templates. Wenn man sie nicht benutzt, werden die doch gar nicht erst kompiliert, geschweige denn gelinkt. :xmas2:



  • Ad aCTa schrieb:

    Wieso? Ich schätze, fast alles in der Standardbibliothek sind Templates.

    Naja, die gesamte C-Bibliothek schon mal nicht (aber ok, da sind wohl mehr Deklarationen).

    Trotzdem liegst du falsch. Weil du mir nicht glauben wirst, habe ich ein Programm geschrieben:

    #include <iostream>
    #include <vector>
    #include <list>
    #include <algorithm>
    
    #include <boost/preprocessor/repetition/repeat.hpp>
    
    #define DEFINE_USELESS_FUNC(Z, N, IDENTIFIER)    \
    void IDENTIFIER ## N(int a, double d, bool b)    \
    {                                                \
        long l = a*d - b;                            \
        std::vector<int> v(100, l);                  \
        v[99] = d;                                   \
        std::sort(v.begin(), v.end());               \
        std::random_shuffle(v.begin(), v.end());     \
        std::cout << v[99] << v[rand() % 100];       \
        std::list<int> w(v.begin(), v.end());        \
        w.sort();                                    \
        std::cout << w.back() << std::endl;          \
    }
    
    #define CALL_USELESS_FUNC(Z, N, IDENTIFIER)      \
    IDENTIFIER ## N(N, 3.1415, false);
    
    // ========== Eigentlicher Code ab hier ==========
    //#define USE_USELESS_FUNC
    
    BOOST_PP_REPEAT(150, DEFINE_USELESS_FUNC, useless)
    
    int main()
    {
        #ifdef USE_USELESS_FUNC
        BOOST_PP_REPEAT(150, CALL_USELESS_FUNC, useless)
        #endif
    }
    

    Die Präprozessormetaprogrammierung ist nur zum Definieren mehrerer Funktionen, sodass man den Unterschied gut sieht.

    So ist die .exe -Datei 7kB gross. Definiere ich USE_USELESS_FUNC , erhöht sich die Grösse auf 127kB. Also irgendwas an deiner Theorie kann nicht ganz stimmen. Kompiliert wurde übrigens auf MSVC++ 2008 im Release-Modus.


Anmelden zum Antworten