Funktionspointer und Funktionspointer als Parameter



  • Schönen guten Abend,

    ich habe folgendes Problem mit dieser Funktion:

    //main.cpp
    #include "main.h"
    MyArray gradient(MyArray x_vektor, double(*f_ptr)(double x_stelle)) {
    
    	double h = 10 ^ (-8);
    
    	
    	//TODO
    
    	return x_vektor;
    }
    
    
    double f(double x_stelle) {
      
            double summ = 0.0;
    
    	summ = summ * summ;
    
    	return summ;
    }
    //main.h
    #pragma once
    #include <iostream>
    #include "MyArray.h"
    
    
    double f (double x_stelle);
    MyArray gradient (MyArray x_vektor,double(*f_ptr)(double x_stelle));
    

    Nun, bekomme die Fehler:

    Fehler C4430 Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.

    Fehler C2146 Syntaxfehler: Fehlendes ";" vor Bezeichner "gradient"

    IDE makiert mir den Prototyp im Header.
    Natürlich, weiß ich, was der Fehler C4430 bedeutet, nur im diesem Fall nicht...
    Bin noch nicht so bewandert mit Funktionspointer.Vielen lieben Dank schonmal für die Hilfe!


  • Mod

    Was ist denn ein MyArray und auf welchem Wege ist es in main.cpp bekannt? Falls die Antwort auf letzteres "weiß ich nicht" ist, dann ist das das Problem 🙂



  • Was soll denn das MyArray sein? Wenn du das in der cpp-Datei verwenden willst, muss es dort auch bekannt sein. Ich rate mal, dass du schlicht das #include "MyArray.h" in der cpp-Datei vergessen hast? (Edit: argh, @SeppJ war schneller)



  • Ach, es tut mir leid.

    MyArray ist eine Klasse, die einfach ein dynamisches Array erstellt und Methoden besitzt, um dieses Array zu verwalten.
    In der main.cpp includiere ich main.h.
    Die IDE zeigt mir auch erst nach dem erstellen den Fehler an, also wenn ich complien möchte.



  • @Herr-Black sagte in Funktionspointer und Funktionspointer als Parameter:

    In der main.cpp includiere ich main.h.

    Sicher? Denn der von dir gepostete code zeigt was anderes.



  • Höchstwahrscheinlich liegt es an

    //main.h
    #pragma once
    #include <iostream>
    #include"main.h" // <- diesem hier!?
    #include "MyArray.h"
    

    Die eigene Datei wieder einzubinden führt zu einer Rekursion und verwirrt den Compiler ;-).



  • @Th69 sagte in Funktionspointer und Funktionspointer als Parameter:

    Höchstwahrscheinlich liegt es an

    //main.h
    #pragma once
    #include <iostream>
    #include"main.h" // <- diesem hier!?
    #include "MyArray.h"
    

    Die eigene Datei wieder einzubinden führt zu einer Rekursion und verwirrt den Compiler ;-).

    Wobei das prama once dass verhindert.
    Ansonsten würde der compiler mit einer recursive include Fehlermeldung irgendwann aussteigen oder wegen RAM mangel abstürzen (keine Ahnung wie gut der pre-processor von den compilern recursive includes erkennen kann)



  • @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    … (keine Ahnung wie gut der pre-processor von den compilern recursive includes erkennen kann) …

    Er erkennt das gar nicht. Deshalb ist der klassische Weg

    // my_header.h
    #ifndef MY_HEADER_H
    #define MY_HEADER_H
    
    … Code im Header …
    
    #endif
    
    


  • @john-0 also #pragma once funktioniert schon mit gcc, clang und msvc.



  • @john-0 sagte in Funktionspointer und Funktionspointer als Parameter:

    @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    … (keine Ahnung wie gut der pre-processor von den compilern recursive includes erkennen kann) …

    Er erkennt das gar nicht. Deshalb ist der klassische Weg

    Was dann bedeuten würde, dass der pre-processor entweder abstürzt oder komplett hängen bleibt wenn es nicht durch include guards oder pragma once verhindert wird


  • Mod

    @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    Was dann bedeuten würde, dass der pre-processor entweder abstürzt oder komplett hängen bleibt wenn es nicht durch include guards oder pragma once verhindert wird

    Oder mit einer sinnvollen Diagnose aussteigt, weil wir nicht in der Steinzeit leben?



  • @SeppJ sagte in Funktionspointer und Funktionspointer als Parameter:

    @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    Was dann bedeuten würde, dass der pre-processor entweder abstürzt oder komplett hängen bleibt wenn es nicht durch include guards oder pragma once verhindert wird

    Oder mit einer sinnvollen Diagnose aussteigt, weil wir nicht in der Steinzeit leben?

    Das war meine ursprüngliche Frage ob das der Pre-processor das kann. Und Laut John-0 scheinbar nicht oder er hat die Frage falsch verstanden


  • Mod

    @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    Das war meine ursprüngliche Frage ob das der Pre-processor das kann. Und Laut John-0 scheinbar nicht oder er hat die Frage falsch verstanden

    Warum sollte er das nicht können? Aber es gibt halt keinen Standard, der vorschreibt, dass er das können muss.



  • Naja, das ist doch schnell ausprobiert:

    $ cat x.h
    #include "x.h"
    
    $ cat x.c
    #include "x.h"
    int main(void) { return 0; }
    
    $ gcc x.c
    In file included from x.h:1,
                     from x.h:1,
                     from x.h:1,
    (... ich habe ein "paar" Zeilen weggeschnitten...)
                     from x.h:1,
                     from x.h:1,
                     from x.c:1:
    x.h:1:15: error: #include nested depth 200 exceeds maximum of 200 (use -fmax-include-depth=DEPTH to increase the maximum)
        1 | #include "x.h"
          |               ^
     ✘ Error 1
    
    

    Also: die Rekursion wird erkannt und bei einer bestimmten Tiefe dann abgebrochen. @john-0 meint vermutlich, dass der Präprozessor nicht wissen kann, bis wie tief die Rekursion sinnvoll ist.


  • Mod

    Bevor jemand fragt: Ein Limit zu haben ist explizit vom Standard erlaubt.

    A #include preprocessing directive may appear in a source file that has been read because of a #include
    directive in another file, up to an implementation-defined nesting limit.



  • @firefly sagte in Funktionspointer und Funktionspointer als Parameter:

    Das war meine ursprüngliche Frage ob das der Pre-processor das kann. Und Laut John-0 scheinbar nicht oder er hat die Frage falsch verstanden

    Du hast die Antwort falsch verstanden. Die Norm fordert von konformen Compilern bestimmte Eigenschaften, das Erkennen von rekursiven Includes gehört nicht dazu. D.h. Du darfst Dich nicht darauf verlassen, dass der Compiler irgend was Sinnvolles machen wird, wenn Du die Include Guards weglässt. #pragma once ist toll, wenn es denn der Compiler unterstützt, aber die Norm garantiert eben nicht, dass ein Compiler diese Eigenschaft besitzt.



  • Hallöchen,

    interessante Antworten. Ich habe mal das rekursive main.h rausgenommen. Leider funktioniert dies immer noch nicht.

    Die Fehler werden beim Prototyp im Header angezeit von der Funktion:

    MyArray gradient (MyArray x_vektor,double(*f_ptr)(double x_stelle));
    

    Bei Funktionen, die kein MyArray zurückgeben, funktioniert es.
    Also müsste es ja etwas mit der Klasse MyArray zu tun haben?

    class MyArray {
    
       private:  
           double* array = nullptr;
    	   int a = 0;
       public:
    	 
    	   MyArray(int size) {
    		   
    	   array=init(size);
    }
    	   ~MyArray() { delete[] this->array; }
    
       void set_Array(int index, double wert);
       double get_Array(int index);
       double length_vektor();
       void print();
       double* operator * (double lambda);
       double* operator + (MyArray& arr);
       double operator[]( int index);
    

    Könnte es daran liegen, dass ich kein Copy und Copy-assigns Constructor geschrieben habe?


  • Mod

    Nach wie vor ist das eher ein Problem mit deinen Includes. Da du aber in deiner Eingangsfrage die relevanten Zeilen weggelassen hast, und seitdem noch wer weiß welche Änderungen gemacht hast, kann das keiner mehr nachvollziehen.

    Daher bitte: Ein minimales, aber vollständiges Beispiel posten, das den Fehler demonstriert. Siehe auch hier, den Abschnitt unten über Codereduzierung.

    PS: Deine Arrayklasse hat, wie du schon selber vermutest, ein großes Problem mit der Ressourcenverwaltung. Aber das wird dir erst zur Laufzeit um die Ohren fliegen, mit deinem Compilerfehler hat das nichts zu tun. Tipp: Deine Klasse macht zu viel. Es soll ja anscheinend sowohl ein dynamisches Array sein, als auch irgendwie so etwas wie ein mathematischer Vektor. Das sind zwei Funktionalitäten, die getrennt gehören. Ein mathematischer Vektor sollte keine Speicherressourcen verwalten. Und falls es hier nicht um einen Lerneffekt bezüglich Ressourcenverwaltung geht, dann ist es auch überhaupt gar nicht nötig, eine dynamische Arrayklasse selber zu implementieren, denn das gibt es schon fertig, std::vector (was ein Zufall, der Name 🙂 )



  • Danke,

    ich habe den Code in der Eingangsfrage bearbeitet.

    Dann werde ist aus der STL die Vektoren benutzten.

    Ja, wollte zusätzlich als Übung eine eigene Klasse schreiben.

    Vielen Dank!



  • @Herr-Black sagte in Funktionspointer und Funktionspointer als Parameter:

    Danke,
    ich habe den Code in der Eingangsfrage bearbeitet.

    Ich bin jetzt total verwirrt: ist dein Fehler jetzt behoben?

    Mit dem Code oben solltest du jetzt beim Übersetzen den Linker-Fehler bekommen, dass ein "main" fehlt. Ansonsten sollte der Code (unter der Annahme, dass dein MyVector korrekt ist) kompilieren.


  • Mod

    @wob sagte in Funktionspointer und Funktionspointer als Parameter:

    @Herr-Black sagte in Funktionspointer und Funktionspointer als Parameter:

    Danke,
    ich habe den Code in der Eingangsfrage bearbeitet.

    Ich bin jetzt total verwirrt: ist dein Fehler jetzt behoben?

    Ja, nachträglich Beiträge zu editieren verwirrt nur. Außerdem fehlt eine MyArray.h in dem Beitrag. Wenn ich rate, dass deine MyArray.h ungefähr so aussieht, wie deine oben gezeigte Definition der Klasse MyArray, dann funktioniert die Übersetzung: https://ideone.com/BqOdCr Das kann also nicht der Code sein, der bei dir den Fehler verursacht, außer der Fehler ist jetzt doch schon behoben. Da ich aber sowohl raten, als auch den Code editieren musste, ist es durchaus möglich, dass ich mir für die fehlenden Teile etwas richtiges ausgedacht habe, wo du einen Fehler hast.


Anmelden zum Antworten