Zugriff auf eine Methode der Erzeugungsklasse?



  • Guten Tag!
    Ich hab mich jetzt hier ein wenig schlau gemacht über mein Problem, aber so richtig weiß ich immer noch nicht wie ich vorgehen soll.

    Ich habe eine Hauptklasse mit Methoden. Aus dieser Hauptklasse erzeuge ich eine weitere Klasse. Nun möchte ich aber auch die Möglichkeit haben aus der gerade eben erzeugten Klasse auf die Methoden der Hauptklasse zuzugreifen. 😉

    Wie soll ich das realisieren mit einer Referenzübergabe oder mit einem Zeiger?

    *this als Übergabeparameter gleich beim Erzeugen der neuen Klasse?

    Ich bin leider noch ein Newbie, also nicht böse sein, wenn die Frage dumm sein sollte.

    Erschwerend kommt noch hinzu, dass die Klassen natürlich in getrennte Dateien stehen. Also ich hab cpp und h Dateien. Ich muß also ein wenig mehr berücksichtigen.

    Ich zeig Euch mal ein kleines Beispiel:

    main_window.h :

    #include "toplevel_w.h"
    
    class Main_window 
    {
         public:
            // Konstruktor
            Main_window();
    
            // Destruktor
            ~Main_window();
    
            void fuelleTextfeld(string); // Funktion, das ein Textarea-field im 
                                         // Main_window mit übergebenen Text füllt
         private:
            Toplevel_w m_ptoplevelw;  // neues Objekt der Klasse Toplevel_w
                                      // Muß ich hier schon etwas modifizieren???
    

    main_window.cpp

    #include "main_window.h"
    
    //Konstruktor
    Main_window::Main_window()
    {
    
    }
    
    //Destruktor
    Main_window::~Main_window()
    {
    
    }
    
    void Main_window::fuelleTextfeld(string text)
    {
       this->Statusbox->insert(text);
    }
    

    toplevel_w.h

    class Toplevel_w()  // <- Muß ich hier etwas modifizieren, wenn mein Problem 
                        // gelöst werden soll?
    {
      public:
        // Konstruktor
        Toplevel_w();
    
        // Destruktor
        ~Toplevel_w();
    
        void drueckeKnopf(); // Funktion, die bei einem Knopfdruck im
                             // Toplevelwindow aufgerufen wird
    }
    

    toplevel_w.cpp

    #include "toplevel_w.h"
    
    // Konstruktor
    Toplevel_w::Toplevel_w()
    {
    }
    
    // Destruktor
    Toplevel_w::~Toplevel_w()
    {
    }
    
    void Toplevel_w::drueckeKnopf()
    {
         string input = lineEdit->text(); // Methode zum Auslesen eines      
                                        // Entry-Feldes
    
         // so und nun das Problem:
         ???.fuelleTextfeld(input); // <- Wie greif ich auf diese Methode zu?
    }
    

    Vielleicht kann hier ja jemand mir ein wenig weiterhelfen, oder sogar schnell mein Beispiel so modifizieren, dass es klappen könnte. 😉
    Würde mich natürlcih sehr freuen.

    Gruß skontox



  • Hi,

    wenn du das wirklich so haben willst - und ich bezweifle irgendwie das das wirklich Sinn hat (vielleicht solltest du dein Design mal überdenken), dann würde ich dem Konstruktor der Klasse Toplevel_w eine Referenz auf die Hauptklasse Main_Window übergeben und das in einer privaten Membervariablen speichern.

    //...
    // Toplevel_w hat eine private Membervariable m_mainWnd
    private:
       Main_Window& m_mainWnd;
    // ...
    
    // und der Konstruktor:
    Toplevel_w( Main_Window& mainWnd ) {
      m_mainWnd = mainWnd;
    }
    

    Jetzt kannst du über diese Membervariable immer auf die Klasse Main_Window zugreifen. Natürlich musst du jetzt beim Deklarieren einer Variable dem Konstruktor auch etwas übergeben!!!

    Ich hoffe, das hat ein bisschen geholfen...

    Mfg, smasher1985



  • Danke für die Antwort!
    Aber leider haut das bei mir nicht hin.

    Ich bekomme eine Fehlermeldung:

    toplevel_w.h:58: error: syntax error before '&' token.

    Muß ich das der Klasse nicht irgendwie bekanntgeben, was "Main_window" überhaupt ist?

    Also includieren oder so?

    Kannst du mir das mal anhand meines Beispiels zeigen. Sprich mal etwas modififieren.

    Das wäre sehr nett.

    Kann ich nicht auch beim Erzeugen der Toplevel_w Klasse in der Datei main_window.h gleich die Referenz auf die Main_window-Klasse übergeben?

    Gruß skontox



  • Ein interessantes Thema und gar nicht so einfach, wie man denkt. Ich stolpere auch immer wieder über das Problem: Wo krieg ich meinen Zeiger auf ein Object her?
    Wenn man das Objectmodell selber programmiert, hab ich mir das eigentlich so angewöhnt:

    #include "parent.h"
    class child
    {
        child(){};
        ~child(){};
    private:
        parent* m_parent;
    public:
        set_parent(parent* p){m_parent = p;};
        parent* get_parent(){return m_parent;};
    }
    
    #include"child.h"
    class parent
    {
        parent(){  child* m_child;
                   m_child = new child;
                   m_child->set_parent(this);
                 }
       ~parent(){...}
    private:
        child* m_child;
    }
    

    Leider gibts hier ganz schnell einen Zirkelbezug. Parent includiert child und child includiert parent. Ich hab auch schon mal mit friend rumexperimentiert. Vielleicht kann ja dazu noch jemand seinen Kommentar schreiben ?!?

    Noch schlimmer wirds, wenn man ne Bibliothek benutzt uns sich nicht sicher ist, wie man nen Zeiger herkriegt. Zum Bleistift:

    CFrameWnd* frame = (CFrameWnd*)AfxGetMainWnd();
    myDocument* myDoc = (myDocument*)frame->GetActiveDocument();
    

    myDocument is natürlich von CDocument abgeleitet und das wieder von CWnd, CFrameWnd).
    Damit kann man sich wochenlang ziemlich erfolglos beschäftigen und man kommt nix weiter. 😞



  • mit forward declarations im header arbeiten.

    implementation in der cpp datei und auch nur da den header einbinden. da gibts keinen Zirkelbezug.



  • Ich hab das hier mit Hilfe eines Kumpels modifiziert:

    main_window.h :

    #include "toplevel_w.h"
    
    class Main_window
    {
         public:
            // Konstruktor
            Main_window();
    
            // Destruktor
            ~Main_window();
    
            void fuelleTextfeld(string); // Funktion, das ein Textarea-field im
                                         // Main_window mit übergebenen Text füllt
         private:
            Toplevel_w m_ptoplevelw;  // neues Objekt der Klasse Toplevel_w
                                      // Muß ich hier schon etwas modifizieren???
    

    main_window.cpp

    #include "main_window.h"
    
    //Konstruktor
    Main_window::Main_window():m_ptoplevelw(this) //oder *this
    {
    
    }
    
    //Destruktor
    Main_window::~Main_window()
    {
    
    }
    
    void Main_window::fuelleTextfeld(string text)
    {
       this->Statusbox->insert(text);
    }
    

    toplevel_w.h

    #include "main_window.h"
    
    class Toplevel_w()  // <- Muß ich hier etwas modifizieren, wenn mein Problem
                        // gelöst werden soll?
    {
      public:
        // Konstruktor
        Toplevel_w(Main_window);
    
        // Destruktor
        ~Toplevel_w();
    
        void drueckeKnopf(); // Funktion, die bei einem Knopfdruck im
                             // Toplevelwindow aufgerufen wird
       private:
          Main_window m_pmw;
    
    }
    

    toplevel_w.cpp

    #include "toplevel_w.h"
    
    // Konstruktor
    Toplevel_w::Toplevel_w(Main_window &tmp)
    {
        m_pmw=tmp;
    }
    
    // Destruktor
    Toplevel_w::~Toplevel_w()
    {
    }
    
    void Toplevel_w::drueckeKnopf()
    {
         string input = lineEdit->text(); // Methode zum Auslesen eines
                                        // Entry-Feldes
    
         // so und nun das Problem:
         m_pmw.fuelleTextfeld(input); // <- Modifiziert
    }
    

    So könnte es klappen, muß ich gleich mal ausprobieren!

    Großen Dank an Snake! 😉

    Gruß skontox



  • Alles schön und gut, aber irgendwie klappt das nicht! 😢

    Gruß skontox



  • Endlich haut es hin! 😉
    Dank der Beiträge von electron und Unregistrierter (forward declaration) hab ich ein neues Beispiel gecoded das jetzt auch läuft und das macht was ich will.
    Da es wahrscheinlich auch andere Newbies interessieren könnte, zeige ich das neue Beispiel nochmal:

    main.cpp

    #include "mainw.h"
    #include "topw.h"
    
    #include <iostream>
    using namespace std;
    
    int main() {
      MainW mw;  // Neue Instanz von MainW wird erzeugt
    
      return 0;
    }
    

    mainw.h

    #ifndef __MAINW__H__
    #define __MAINW__H__
    
    #include <string>
    #include <iostream>
    using namespace std;
    
    class TopW; // hier ist die "forward declaration"
    
    class MainW {
    public:
    
        MainW(); // Konstruktor
    
        ~MainW(); // Destruktor
    
        void who_are_you(string); // Methode zur Ausgabe von einem übergebenen
                                  // String
    
     private:
         TopW* m_tw; // Private Member Variable 
    };
    
    #endif
    

    mainw.cpp

    #include "mainw.h"
    #include "topw.h"
    
        MainW::MainW()
        {
             m_tw = new TopW;           // Neue Instanz von TopW wird erzeugt
             m_tw->set_parent(this);    // Methode "set_parent()" der Klasse TopW
                                        // wird aufgerfufen und bekommt ein
                                        // This-Objekt (Die jetzige Instanz
                                        // dieser Klasse) übergeben.
        }
    
        MainW::~MainW()
        {
        }
    
    void MainW::who_are_you(string text) {
      cout << text << endl;    // hier wird der übergebene String ausgegeben
    }
    

    topw.h

    #ifndef __TOPW__H__
    #define __TOPW__H__
    
    #include <string>
    using namespace std;
    
    class MainW;  // Hier ist die "forward declaration"
    
    class TopW {
    public:
    
       TopW(); // Konstruktor
    
       ~TopW(); // Destruktor
    
       void set_parent(MainW*); // Diese Methode erwartet ein Objekt vom Typ MainW
    
       void call();             // Diese Methode ruft die Methode
                                // "who_are_you(string)" der Klassse MainW auf 
    
    private:
        MainW* m_mw; // Private Member Variable
    };
    
    #endif
    

    topw.cpp

    #include "topw.h"
    #include "mainw.h"
    
        TopW::TopW()
        {
        }
    
        TopW::~TopW()
        {
        } 
    
     void TopW::set_parent(MainW* p)
     {
        	m_mw = p;
        	this->call();   // Methode call() dieses TopW-Objektes wird aufgerufen 
     }
    
     void TopW::call()
     {
        	string var="Nielsi";    // Variable vom Typ String wird deklariert und
                                    // mit "Niels" initialisiert
        	m_mw->who_are_you(var); // Aufruf der Methode aus Klasse MainW, 
        	                        // die wir übergeben bekommen haben
     }
    

    Ich hoff ich konnte damit auch anderen Newbies weiterhelfen. 😉

    Gruß skontox



  • Ich habs mal überflogen und man sollte vielleicht noch anmerken, dass die Namen der Include-Guards ungültig sind (Faustregel: Finger weg von allem, was mit einem _ anfängt, das ist für die Implementierung da). "using namespace" hat in Headern nichts zu suchen, weil du damit jedem Benutzer des Headers den namespace auch aufzwingst. Außerdem wird das mit new angelegte TopW nirgends freigegeben. Ich würde hier lieber topw.h includen und das Objekt direkt, nicht über einen Zeiger als Member anlegen. Solange sich die Header nicht gegenseitig includen, ist doch alles in Butter. Die Pointer-Variante ist so jedenfalls mehrfach buggy.



  • Besten Dank operator void!

    Finde ich gut, dass Du mir den Hinweis gegeben hast! 😉

    Gruß skontox



  • Auf Anraten von operator void habe ich das Beispiel nochmal modifiziert.

    Ich hoffe ich habe alles berücksichtig was mir operator void zugetragen hat:

    main.cpp

    #include "mainw.h"
    
    #include <iostream>
    using namespace std;
    
    int main() {
      MainW mw;  // Neue Instanz von MainW wird erzeugt
    
      return 0;
    }
    

    mainw.h

    #ifndef MAINW__H__
    #define MAINW__H__
    
    #include <string>
    #include <iostream>
    
    #include "topw.h"
    
    class MainW {
    public:
    
        MainW(); // Konstruktor
    
        ~MainW(); // Destruktor
    
        void who_are_you(std::string); // Methode zur Ausgabe von einem
                                       // übergebenen String
    
     private:
         TopW m_tw; // Private Member Variable  
    };
    
    #endif
    

    mainw.cpp

    #include "mainw.h"
    
    using namespace std;
    
    MainW::MainW()
     {
           m_tw.set_parent(this); // Methode set_parent der Klasse TopW wird   
                                  // aufgerfufen und bekommt ein This-Objekt
                                  // (Die jetzige Instanz dieser Klasse)
                                  // übergeben.
     }
    
     MainW::~MainW()
     {
     }
    
    void MainW::who_are_you(string text) {
      cout << text << endl;    // hier wird der übergebene String ausgegeben
    }
    

    topw.h

    #ifndef TOPW__H__
    #define TOPW__H__
    
    #include <string>
    
    class MainW;  // Here is the forward declaration
    
    class TopW {
    public:
    
       TopW(); // Konstruktor
    
       ~TopW(); // Destruktor
    
       void set_parent(MainW*); // Diese Methode erwartet ein Objekt vom Typ MainW
    
       void call();  // Diese Methode ruft die Methode
                     //"who_are_you(string)" der Klassse MainW auf
    
    private:
        MainW* m_mw; // Private Member Variable
    
    };
    
    #endif
    

    topw.cpp

    #include "topw.h"
    #include "mainw.h"
    
    using namespace std;
    
    TopW::TopW()
    {
    }
    
    TopW::~TopW()
    {
    } 
    
     void TopW::set_parent(MainW* p)
     {
        	m_mw = p;
        	this->call();   // Methode call() dieses TopW-Objektes wird aufgerufen 
     }
    
     void TopW::call()
     {
        	string var="Nielsi";    // Variable vom Typ String wird deklariert
                                    // und mit "Niels" initialisiert
        	m_mw->who_are_you(var); // Aufruf der Methode aus Klasse MainW, 
        	                        // die wir übergeben bekommen haben
     }
    

    So, ich hoffe das war alles!

    Gruß skontox


Anmelden zum Antworten