Klassen funktion in main nutzen und umgekehrt



  • Hey leute ich hab ein Problem und bin irgendwie zu doof es selbst zu Lösen.

    Ich habe eine Window Klasse mit einem Key Callback, welches dann wiederum in der Klasse etwas ändern soll. Ich möchte es wegen übersichtlichkeit und weil ich dort ständig rein schreibe nicht in der Klasse haben sondern außerhalb.

    class Window{
    private:
    
       setKeyCallback(myCallback);
       mainLoop(){
          while(!close){
              ...something...
              pollEvents();
          }
       }
    };
    Window app;
    void myCallback(...something...){
       app.changeSomething();
    }
    

    Problem hierbei, er sagt beim SetCallback myCallback wäre nicht gefunden worden, ich kann aber auch nicht über der Klasse den kram definieren, weil dann app.changeSomething nicht funktionert. Was muss ich tun?


  • Mod

    Meinst du so? Dein Beispiel ist leider ziemlich unvollständig, daher ist es ein Ratespiel, was du genau möchtest

    #include <iostream>
    using namespace std;
    
    class Foo
    {
    private:
    	void (*callback)(Foo&);
    public:
    	void set_callback(void (*function)(Foo&)){callback = function;}
    	void trigger_callback(){callback(*this);}
    	int value;
    };
    
    void my_callback(Foo &f)
    {
    	f.value = 42;
    }
    
    int main() {
    	Foo f;
    	f.set_callback(my_callback);
    	f.trigger_callback();
    	cout << f.value;
    }
    

    PS: Kannst du das hier erläutern?

    Ich möchte es wegen übersichtlichkeit und weil ich dort ständig rein schreibe nicht in der Klasse haben sondern außerhalb.



  • @SeppJ ich habe eine Klasse mit 1500 Zeilen Code und keine Lust noch etwas außer die Zugriffspunkte (Getter, Setter, callbacks, Funktionen an diese ich die Daten sende) dort rein zu implementieren. das wird viel zu viel und ist ja auch garnicht Sinn der Sache. Die eigentlichen Sachen sollen im Main Code passieren, dann schick ich das zur Klasse, welche dann alles Verarbeitet Rendert usw bis es dann auf den Bildschirm kommt.



  • @SeppJ nein (könnte auch sein dass ich nicht verstehe was das ist) eigentlich genau so wie es oben steht. Ich habe eine Klasse, und Funktionen außerhalb der Klasse, welche dann wieder was an die Klasse senden. z.B. ein keyCallback. Ich möchte selber konfigurieren, was bei welchem key passiert, aber das nicht in die Klasse schreiben, weil dort projektspezifische Sachen nicht rein gehören. Diese Funktion, welche außerhalb ist, soll dann wieder der Klasse soetwas wie: "class.camX(-10)" ausführen.

    
    class Foo{
    public:
       void camX(int xMovement) {
          camX += xMovement;
       }
    
    private:
       camX = 0;
       setKeyCallback(..., **myCallback**);
    };
    Foo foo;
    
    void **myCallback**(int key, int action){
        if(key == 0x41 && action == PRESS) foo.camX(10);
    }
    int main(){}
    

    wie gesagt, das Problem ist einfach, dass ich Foo foo; und die Definition der Funktion myCallback nicht nach oben machen kann, da sonst Foo nicht definiert ist. Das braucht aber die Funktion setKeyCallback weil sie sonst myCallback nicht finden kann. statics zu benutzen generiert nur 1000 weitere errors und ist auch umständlich, wenn es nur ein Setter ist.


  • Mod

    Ich meine ja immer noch, dass mein Code genau das vorführt, wonach du vermeintlich fragst. Zeig dein Beispiel doch mal mit korrekter, vollständiger C++-Syntax, sonst artet dieses Ratespiel nur noch weiter aus. Woher sollen wir wissen, was du mit so etwas wie setKeyCallback(..., **myCallback**); meinst?

    ich habe eine Klasse mit 1500 Zeilen Code

    Du machst etwas krass falsch. Benutzt du Klassen als Namespaces?

    zur Klasse, welche dann alles Verarbeitet Rendert usw

    Ein weiterer Hinweis, dass du etwas krass falsch machst. Die Funktion einer Klasse darf nie zu einer Auflistung werden, und ganz bestimmt nicht "und so weiter" enthalten. Eine Klasse stellt genau eine Sache dar!

    globales Foo foo; im Code

    Noch ein Hinweis, dass du Klassen für irgendein anderes Konzept (vermutlich Namespaces) missbrauchst.

    Vielleicht löst sich dein Problem ganz von alleine, wenn du deine Klassen(!) sauberer, mit klareren Aufgabengebieten definierst.



  • @SeppJ ja die klasse stellt eine sache da, ein vulkan setup mit glfw als Oberfläche, ich bin mir da relativ sicher dass eine Class Window da relativ simpel ist. Was ich machen will, oder am Ende haben will, ist eine Klasse, mit zum Beispiel der Funktion add Triangle. Die Klasse macht und tut dann im Hintergrund, sodass zum Beispiel indices erzeugt werden, das ganze dann in den Command buffer geklatscht wird und anderes (so verarbeiten, dass das Dreieck am Ende auf dem Bildschirm landet). Und nein es ist nicht unsinvoll das alles in eine Klasse zu machen, da man dann mit einer erschafften Klasse ein ganzes Window samt access points parat hat. Der Befehl setKeyCallback(..., myCallback); ist in Wirklichkeit einfach nur GLFWwindow window; glfwSetKeyCallback(window, myCallback); Verstehe nicht was daran jetzt so rätzelhaft ist, danke für die Hilfe trotzdem


  • Mod

    @thinki sagte in Klassen funktion in main nutzen und umgekehrt:

    Der Befehl setKeyCallback(..., myCallback); ist in Wirklichkeit einfach nur GLFWwindow window; glfwSetKeyCallback(window, myCallback); Verstehe nicht was daran jetzt so rätzelhaft ist, danke für die Hilfe trotzdem

    Die Erklärung macht es nur noch rätselhafter. Wie soll so etwas innerhalb einer Klassendefinition stehen? Bitte verwende echte C++-Syntax! Wenn du denkst, das wäre echte C++-Syntax, dann ist dies dein Problem!



  • class Window{
    public:
       void addTriangle(int edge1X, int edge1Y, int edge2X, int edge2Y, int edge3X, int edge3Y){
       ...mache alles damit das Dreieck von Vulkan gerendert werden kann...
       }
       void run(){
          initWindow();
          initVulkan();
          mainLoop();
          cleanup()
       }
       void moveCamX(float amount){
       camX += amount;
       }
       void moveCamY(float amount){
          camY += amount;
       }
       void moveCamZ(float amount){
          camZ += amount;
       }
    private:
       float camX = 0; camY = 0; camZ = 0;
       GLFWwindow window;
       void initWindow(){
       ...GLFW init Stuff...
          glfwSetKeyCallback(window, keyPressed);
       ...
       }
       void initVulkan(){
       ....alles was vulkan so braucht...
        }
       void mainLoop(){
          while (!glfwWindowShouldClose){
                calcFrame();
              ...render Stuff....
          }
       }
       void cleanup(){
       ...alle Vulkan sachen Zerstören...
       }
    };
    
    Window app;
    bool isKeyPressed(int keyCode, int key, int action){
       if(key == keyCode && action == GLFW_PRESS) return true;
       return false;
    }
    void keyPressed(GLFWwindow *window, int key, int keyCode, int action, int mods){
       if(isKeyPressed(GLFW_KEY_KP_8, key, action)) app.moveY(1.0f);
       if(isKeyPressed(GLFW_KEY_KP_5, key, action)) app.moveY(-1.0f);
       if(isKeyPressed(GLFW_KEY_KP_4, key, action)) app.moveX(-1.0f);
       if(isKeyPressed(GLFW_KEY_KP_6, key, action)) app.moveX(1.0f);
    }
    
    void calcFrame(){
       app.addTriangle(100, 50, 50, 100, 200, 200);
    ...all mein späterer code... 
    }
    int main(){
       try{
       app.run();
       } catch(const exception&e ){
          cerr  << e.what() << endl;
          return EXIT_FAILURE;
       }
    }


  • Mein Problem ist einfach nur: Die Funktion glfwSetKeyCallback(window, keyPressed); braucht die definition über der Klasse, sonst sagt der compiler: "keyPressed undeclared identifier" ebenso mit calcFrame(); wenn ich diese Sachen jedoch über die Klasse schiebe, kann ich nicht mehr Window app; schreiben, weil die Klasse Window dort noch nicht vorhanden ist. Dem ensprechend funktioniert dann auch die funktion keyPressed nicht mehr, weil diese ja dinge wie app.moveY(1.0f) enthält.

    PS: mir is gerade aufgefallen, dass der Titel nicht wirklich zu meinem Problem passt, ich hoff das ist nicht so schlimm


  • Mod

    Was du brauchst, ist einfach nur eine Forward-Deklaration. Außerdem zwingt dich doch niemand die Funktionsdefinitionen direkt in die Klasse zu schreiben (und wahrscheinlich solltest du es auch nicht…), d.h. alternativ kannst du Window::intiWindow auch ganz woanders definieren, wo die Sachen alle bekannt sind, die du nutzen möchtest.



  • kannst du bitte nen Beispiel machen, ich verstehe nicht ganz was du meinst :' )


  • Mod

    Forward-Deklaration:

    int foo();  // Kann man einfach so im Programm deklarieren, so oft man will. Nuyn weiß der Compiler, es gibt ein foo(), das int liefert. Das reicht.
    
    void bar()
    {
    	std::cout << foo();  // Wir können foo benutzen, obwohl es noch nicht definiert ist
    }
    
    int foo()  // Foo definieren wir einfach irgendwo ganz woanders
    {
    	return 42;
    }
    

    Das ist ungeheuer wichtig, das zu kennen, denn das ist, wie Header funktionieren! Guck dir das genauer an!

    Klassenmember einfach irgendwo anders definieren:

    class Foo
    {
    public:
    	void bar();   // Können wir auch einfach so deklarieren, ohne genaue Definition
    };
    
    
    int foo()
    {
    	return 42;
    }
    
    
    void Foo::bar()
    {
    	std::cout << foo();   // Wir konnen foo nutzen, obwohl es noch nicht bekannt war bei der ersten Deklaration von Foo::bar
    }
    

    Auch dies ist ungeheuer wichtig, weil man so den Code der Klasse von der Klassendefinition loslösen kann, was dann auch Anwendung für Header hat!

    Da fehlen dir aber wichtigste Grundlagen. Das wird ja sicher nicht das einzige sein, was du verpasst hast. Bevor du anderer Leute Frameworks benutzt, noch dazu C-Frameworks, musst du die Sprache an sich besser lernen! Hier brauchst du sogar zwei Sprachen in denen du Fit sein musst. Du musst erst einmal ein paar eigene Programme in C++ (und hier auch C) geschrieben haben, bevor du ein so kompliziertes Framework benutzen kannst.



  • ahhh danke jetzt check ich das



  • aber ich muss dann doch auch die Parameter schon in die Funktion schreiben?

    //das hier ist falsch?
    void doSomething();
    
    int counter = 0;
    void doSomething(int x){
       counter +=1;
    }
    
    //das hier ist richtig?
    
    void doSomething(int x);
    
    int counter = 0;
    void doSomething(int x){
       counter += 1;
    }
    

  • Mod

    Ja, du musst das zweite schreiben. Guck dir dieses und andere Themen unbedingt in einem Lehrbuch an! So ein kleiner Forenbeitrag kann das nicht ausreichend erklären.



  • @SeppJ kannst du mir ein gutes nennen? ich kenne keins und aus den 200 in der Liste ist das dann doch schwer das richtige zu finden


  • Mod

    200? Da sind zwei die in der Kategorie für Anfänger angeführt sind. Und vielleicht 20 insgesamt. Bitte lies Texte genau und denk über sie nach!



  • @SeppJ ich bin jetzt mal auf cplusplus.com gegangen, das ist auch prima danke, aber du solltest mal die restlichen links überprüfen und neu anlegen, ein paar sind garnicht mehr erreichbar.


Log in to reply