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 ūüôā


Log in to reply