Funktionspointer und Funktionspointer als Parameter



  • @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.



  • Danke für die Mühe!

    Der Fehler tritt nicht in der Klasse MyArray auf. Dachte nur, weil die Funktion, die ein Objekt dieser Klasse aufruft, Probleme macht.

    //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));
    

    In der Zeile 8. tritt der Fehler auf:

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

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

    Dieser Fehler kommt erst, wenn ich übersetzen möchten. Hier die main.cpp, wo der Rumpf der Funktion definiert wird.

    //main.cpp
    #include "main.h"
    MyArray gradient(MyArray x_vektor, double(*f_ptr)(double x_stelle)) {
    
    	double h = 10 ^ (-8);
    
    	
    	//TODO
    
    	return x_vektor;
    


  • Hast du evtl. einen Syntax-Fehler in "MyArray.h" (z.B. kein abschließendes Semikolon nach der schließenden Klammer der Klasse MyArray)?

    Ansonsten zeige mal die gesamte "MyArray.h".



  • Fehler gefunden, es lag an ein #include "MyArray.h" was sehr weit runtergerutscht ist. Somit ist der gute Präprozessor nicht fertig geworden.
    Vielen Dank für die Hilfe! Sowas blödes...


Anmelden zum Antworten