Zugriff von Methode einer Klasse auf Objekt in der main



  • Hallo zusammen,

    es gibt ja sachen in der C++ Programmierung die funktionieren und auch spass machen aber manchmal kommt man an stellen an denen man sich denkt, was haben sich die Entwickler dabei nur gedacht 🙂

    class A
    {
    //Allerdings wird in dieser Funktion ein Objekt als Parameter verwendet.
    //Ich will ja nicht ein neues Objekt verändern sondern ein bereits bestehendes.
        void veraendereZahl(B b)
        {
           b.zahl = 5;
        }
    }
    
    class B
    {
       int zahl;
    
    }
    
    int main()
    {
       B einObjekt;
    }
    

    Ich möchte das Attribut "zahl" aus dem Objekt "einObjekt" durch die Funktion einer anderen Klasse verändern.
    Das ist jetzt nur ein vereinfachtes Beispiel. Aber spiegelt mein Problem exakt wieder.

    Was ich bis jetzt versucht habe:
    Bei der Vererbung habe ich die Attribute mit übernommen. Damit hätte dann class A ebenfalls das Attribut zahl - was aber immer noch keinen Einfluss hat auf DAS Objekt von B.

    Für friend-Funktionen und friend-Klassen müsste ich ebenfalls ein neues Objekt erstellen, was ebenfalls das Problem nicht löst,da nicht einObjekt verändert wird, sondern das Attribut eines neuen Objektes.

    Gibt es nicht eine Möglichkeit, sodass ich in der Definition einer Funktion in der Klasse A auf ein bereits initialisiertes Objekt der Klasse B in der Main zugreifen/ändern kann?
    Wenn nicht , dann welche andere Möglichkeit gibt es dann?
    Ich habe keine Idee mehr.

    Ich möchte mich im voraus für jeden Beitrag bedanken !!!
    Vllt kann mir ja jemand helfen.



  • #include <iostream>
    
    class B;
    
    class A 
    { 
    //Allerdings wird in dieser Funktion ein Objekt als Parameter verwendet. 
    //Ich will ja nicht ein neues Objekt verändern sondern ein bereits bestehendes. 
    public: // Das kennst du nicht? Oo
        void veraendereZahl(B& b); // Referenz, wenn du keine Kope willst
    }; // fehlte
    
    class B 
    {
    public: // ...
       int zahl; 
    
    }; // fehlte
    
    void A::veraendereZahl(B& b)
        { 
           b.zahl = 5; 
        } 
    
    int main() 
    { 
       B einObjekt;
       A a;
       a.veraendereZahl(einObjekt);
       std::cout << einObjekt.zahl;
    }
    

    Da waren ohne Ende Fehler drin, die ich erst mal korrigieren musste. Dass du z.B. eine Kopie statt einer Referenz übergeben hast, zeugt irgendwie von völligem Unverständnis.

    Was das Problem mit den gegenseitigen Abhängigkeiten angeht: Das ist einfach nur dumm, da muss ich dir zustimmen. Dass das so ist, liegt daran dass man damals das Kompilierungsmodell von C übernommen hat (irgendwann 199x), welches für C++ aber überhaupt nicht geeignet ist. Wird mit C++17 vermutlich gefixt. (Noch ein paar Regeln ändert was partial template specialization angeht, und C++ ist nicht mehr völlig broken, yaaay! :D)



  • Vielen Dank für deine Antwort cooky451!
    Du hast auch noch alle Kleinigkeiten korrigiert - DANKE 🙂

    Ich habe das Problem möglichst abstrakt geschildert sodass das Augenmerk auf die main Funktion und die Funktion veraendereZahl(B& b); gerichtet ist.

    Ich glaube wir kommen dem Problem durch deine Antwort viel näher.
    In der Main hast du geschrieben:
    a.veraendereZahl(einObjekt);

    Ich möchte jedoch innerhalb der Funktion veraendereZahl() auf einObjekt, welches in der main angelegt wurde, zugreifen/verändern.

    in einer cpp würde dann das so aussehen zB

    void A::veraendereZahl(???)
    {
        ...
        einObjekt.zahl=1;
    }
    

    aber das funktioniert nicht. einObjekt ist zwar vorher in der main angelegt worden,aber innerhalb der Definition einer anderen Klasse wird es nicht erkannt. Ich will nämlich keine Kopie des Objektes einObjekt erstellen noch will ich ein neues Objekt aus der Klasse B erstellen, sondern genau dieses Objekt aus der Main verändern.

    this Zeiger wäre perfekt aber er denkt natürlich bei mir dass das der this Zeiger von Klasse A ist. Ich frage mich echt wie sich das - eigtl sollte es ein grundlegendes Problem sein - lösen lässt.

    Viele Grüße



  • Genau das tut der Code von cooky. Hast du dir die Ausgabe angesehen?
    Du übergibst eine Referenz. Eine Referenz ist nur ein Aliasname für ein anderes Objekt, in diesem Fall, das aus der main().



  • Hallo Nathan,

    vielen Dank für deine Antwort!
    ich versuche das noch ein wenig näher an mein Problem zu bringen.

    class B;
    
    //a.h
    class A 
    { 
     Q_OBJECT  //Ist notwendig um SLOTS in Qt funktionieren zu lassen
    public:
        void fenster();
    
    public slots: 
        void veraendereZahl(B& b); // Referenz, wenn du keine Kope willst
    };
    

    Hier wird ein Fenster erstellt mit einem Button.Es funktioniert auch alles also auch andere Slots die keinen Parameter haben und ebenfalls selbstdefiniert sind.
    Wenn also auf den Button geklickt wird, soll er das Attribut zahl vom Objekt einObjekt aus der Main verändern. Ist das überhaupt möglich?
    Eigtl müsste es ja, sonst könnte man ja nichts an grafischen Benutzeroberflächen
    abändern im Laufe des Betriebes wie Fenstergrößen o.ä.

    //a.cpp
    #include "a.h"
    
    void A::fenster()
    {
       connect(Button, SIGNAL(clicked()), this, SLOT(veraendereZahl(B &b)));
    
       //Evtl zum Testen
       std::cout << einObjekt.zahl;
    }
    
    void A::veraendereZahl(B& b)
    {
         b.zahl = 2; 
    }
    
    //b.h
    class B 
    {
    public: 
       int zahl; 
    
    };
    
    int main() 
    { 
       B einObjekt;
       einObjekt.zahl=1;
       A a;
       //a.veraendereZahl(einObjekt);
       //std::cout << einObjekt.zahl;
    }
    


  • Du willst also das beim Klick auf einen Button, das Objekt B aus der main() verändert wird?
    Dann musst du dir im Konstruktor von A einen Pointer auf B geben lassen, den du dann in der entsprechenden Funktion, die beim Buttonclick aufgerufen wird, bearbeitest.



  • Ich möchte deine Frage mit JA beantworten. Du hast es jetzt.

    Habs mit vielen unterschiedlichen Methoden ausprobiert mithilfe eines Pointers die Adresse zu referenzieren, aber es kommt stets folgende Meldung:

    Object::connect: No such slot A::veraendereZahl(p)
    

    p ist dabei ein Pointer vom Typ class B, der auf einObjekt zeigt.

    Normalerweise kommt diese Meldung nur dann wenn die Funktion nicht im SLOT Bereich steht in der HEADER oder wenn Q_OBJECT nicht anfangs angegeben wurde. Aber das habe ich berücksichtigt.
    Es ist stark anzunehmen, dass es Inkonsistenzen zwischen der aufgerufenen Funktion und der Definition gibt, evtl sogar nur im Argument.

    Vielleicht könntest du einen Lösungsvorschlag zu dem angegebenen Beispiel geben - das wäre sehr hilfreich. Ich könnte es ausprobieren so wie du das verstanden hast.

    Vielen Dank Nathan !



  • Du solltest keinen Pointer uebergeben, oder? A nimmt doch eine Referenz auf.

    Sieht ein bisschen so aus, als haettest du das Problem zu stark vereinfacht, damit es wirklich verstanden und dir auf moeglichst elegante Art geholfen werden kann.



  • Josua schrieb:

    Ich möchte deine Frage mit JA beantworten. Du hast es jetzt.

    Habs mit vielen unterschiedlichen Methoden ausprobiert mithilfe eines Pointers die Adresse zu referenzieren, aber es kommt stets folgende Meldung:

    Object::connect: No such slot A::veraendereZahl(p)
    

    p ist dabei ein Pointer vom Typ class B, der auf einObjekt zeigt.

    Normalerweise kommt diese Meldung nur dann wenn die Funktion nicht im SLOT Bereich steht in der HEADER oder wenn Q_OBJECT nicht anfangs angegeben wurde. Aber das habe ich berücksichtigt.
    Es ist stark anzunehmen, dass es Inkonsistenzen zwischen der aufgerufenen Funktion und der Definition gibt, evtl sogar nur im Argument.

    Vielleicht könntest du einen Lösungsvorschlag zu dem angegebenen Beispiel geben - das wäre sehr hilfreich. Ich könnte es ausprobieren so wie du das verstanden hast.

    Vielen Dank Nathan !

    A speichert als Member einen Pointer auf B, der in der main() gesetzt wird (über Konstruktor o.ä.). In der Funktion verändereZahl wird dann dieser Pointer genutzt um auf B zuzugreifen, der Parameter ist überflüssig.
    Und diese Funktion übergibst du dann connect().

    Es könnte auch eleganter gehen, aber ich bezweifle, dass connect() std::function bzw. ein beliebiges Funktionsobjekt erwartet.



  • @Stiefel2000:
    Ja, das ist mir auch nach der zweiten/dritten Nachricht aufgefallen, dass ich anfangs viel zu einfach das Problem dargestellt habe. Vielen Dank auch dir

    @Nathan:
    Vielen Dank für deine Hilfe.
    Ich habe es genauso gemacht und es hat genauso funktioniert !
    Jetzt kann ich dadurch noch viel mehr Sachen verändern/einbauen 🙂


Anmelden zum Antworten