Auf einem Object in einem anderem Modul zugreifen



  • Hallo,
    hat Jemand dafür vieleicht eine Lösung.
    Ich habe eine Klasse Form1, eine Klasse rs232 sowie ein CPP Modul
    comunication.
    Im Header der Klasse Form1 erzeuge ich eine Zeiger rs232* com;
    Im Konstruktor von Form1 erzeuge ich ein Objekt der Klasse rs232
    com = new rs232;
    Ich möchte nun im Modul comunication auf das im Form1 erstelle Objekt
    zugreifen com->......., ohne die Klasse angeben zu müssen Form1->com->...
    Wie bekomme ich den Zeiger des Objekts com zum Modul comunications.
    Die instanz des Objekts com kann ich ja nicht im Header von Form1 erzeugen.

    Sprich ich möchte die Instanz eines Objekts nur einmal erzeugen und
    sie allen Klassen über den Header bekannt machen.



  • Such mal nach Singleton, das ist ein Entwurfsmuster (design pattern), das Dein Problem lösen könnte.
    Kurzgefasst brauchst die Klasse dazu folgendes:
    1. Einen privaten Konstruktor. Die Klasse ist folglich nicht mehr von außen instanziierbar.
    2. Eine statische Methode, die eine Instanz der Klasse zurückgibt.

    Problematisch ist dabei natürlich das Freigeben von Ressourcen. In Deinem Fall wäre nicht nur Speicher dauerhaft belegt, sondern auch
    ein COM-Port (wenn ich das richtig interpretiert habe).

    Ansonsten könntest Du natürlich auch jeweils die Konstruktoren der Objekte, die eine Instanz der Klasse benötigen, um einen Zeiger auf
    eine Instanz der Klasse erweitern.

    Gruß,

    Alexander



  • Hallo Alexander

    die Instanz des Objects erzeuge sowie lösche ich in einer Klasse.

    Ich möchte aber über den Header dieser Klasse den Zeiger auf das
    Object an andere Klassen übergeben, so das diese auf das
    Object zugreifen können.



  • So funktioniert es:

    In der Klasse fmain_window

    rs232* com;
    Tfmain_window *fmain_window;
    //---------------------------------------------------------------------------
    __fastcall Tfmain_window::Tfmain_window(TComponent* Owner)
         : TForm(Owner)
    {
         com = new rs232;                 //Object Instanzieren
         com->baudrate = 56000;
         com->comport  = "com1";
         com->timeout = 1000;
    }
    

    In der Klasse fthresholds wird dem Linker der Objectzeiger als extern
    mitgeteilt

    extern rs232* com;
    Tfthresholds *fthresholds;
    //---------------------------------------------------------------------------
    __fastcall Tfthresholds::Tfthresholds(TComponent* Owner)
    	: TForm(Owner)
    {
         com->write_rs232(0xaa);
    }
    


  • Fällt diese Lösung nicht in die Kategorie "Globale Variablen"?
    Was spricht eigentlich dagegen - wie weiter oben schon vorgeschlagen - der Klasse Tfthresholds einen Konstruktor zu verpassen,
    die als zusätzliches Argument einen Zeiger rs232* enthält? Sauberer wäre das allemal, da ja die Klasse Tfthresholds offenbar
    unbedingt eine Instanz von rs232 benötigt.

    Gruß,

    Alexander



  • Alexander Kempf schrieb:

    Was spricht eigentlich dagegen - wie weiter oben schon vorgeschlagen - der Klasse Tfthresholds einen Konstruktor zu verpassen,
    die als zusätzliches Argument einen Zeiger rs232* enthält? Sauberer wäre das allemal, da ja die Klasse Tfthresholds offenbar
    unbedingt eine Instanz von rs232 benötigt.

    Die Klasse Tfthresholds hat einen Konstruktor, was meist du mit "die als
    Argument einen zusätzlichen Zeiger rs2323* enthält"

    __fastcall Tfthresholds::Tfthresholds(TComponent* Owner)
    	: TForm(Owner)
    {
         com->write_rs232(0xaa);
    }
    

    Wie würde das aussehen?



  • hermes schrieb:

    Wie würde das aussehen?

    Ungefähr so:

    //header fthresholds.h
    class rs232; // Forward-Deklaration
    class Tfthresholds: public TForm // nur geraten, aber bei dem Konstruktor sehr wahrscheinlich
    {
    public:
      __fastcall Tfthresholds(TComponent* Owner, rs232* RS232);
      __property rs232* RS232 = {read=FRS232};
    private:
      rs232* FRS232;
    // ...und halt der ganze Rest
    };
    
    //Implementierung fthresholds.cpp
    __fastcall Tfthresholds::Tfthresholds(TComponent* Owner, rs232* RS232)
    	: TForm(Owner)
    {
      // Vielleicht noch Überprüfen auf NULL-Pointer oder sonstiges
      FRS232 = RS232;
      RS232->write_rs232(0xaa); // Weitere Zugriffe über die Eigenschaft RS232
    }
    

    Sollte der Konstruktor die einzige Stelle sein, an der ein Zugriff auf die rs232-Instanz erfolgt, kannst Du Dir die member-
    Variable und die Eigenschaft natürlich sparen, aber dann würde ich auch keinerlei Sinn darin erkennen können.
    Wichtig ist hier natürlich, das Formular (sofern ich mit meiner Vermutung richtig liege) nicht automatisch erstellen zu lassen,
    sonder im Code per new bzw. delete zu erzeugen bzw. freizugeben, da sonst automatisch ein virtueller Standard-Konstruktor ohne
    das neue rs232*-Argument bei der Instanziierung aufgerufen wird (und die member-Variable damit nicht initialisiert wäre).

    Den Code habe ich nicht getestet. Falls Du irgendwas daran nicht verstehst, dann frag halt nochmal nach.

    Gruß,

    Alexander



  • Hallo Alexander,
    danke für das Beispiel.

    class rs232; // Forward-Deklaration
    Ist das das gleiche wie extern?

    class rs232; // Forward-Deklaration
    class Tfthresholds: public TForm 
    {
    public:
      __fastcall Tfthresholds(TComponent* Owner, rs232* RS232);
      __property rs232* RS232 = {read=FRS232};
    private:
      rs232* FRS232;
    // ...und halt der ganze Rest
    };
    

    Der Konstruktor übergibt einen Zeiger rs232* RS232, damit der Zeiger bekannt ist die Forward-Deklaration (könnte man nicht auch den Header der Klasse rs232
    includieren?)

    Nun erzeugst du eine Eigenschaft
    __property rs232* RS232 = {read=FRS232};

    //Implementierung fthresholds.cpp
    __fastcall Tfthresholds::Tfthresholds(TComponent* Owner, rs232* RS232)
        : TForm(Owner)
    {
      // Vielleicht noch Überprüfen auf NULL-Pointer oder sonstiges
      FRS232 = RS232;
      RS232->write_rs232(0xaa); // Weitere Zugriffe über die Eigenschaft RS232
    }
    

    Und initialisierst die Eigenschaft mit dem im Konstruktor übergebenen Zeiger.
    FRS232 = RS232;

    Nun kann ich über die Eigenschaft RS232 auf alle Variablen, sowie Methoden der Klasse rs232 zugreifen.

    Ich kann dann aber immer noch nicht auf das Object com der Klasse rs232
    das in einer anderen Klasse (fmain_window)instanziert wurde zugreifen oder?
    Klasse fthresholds:
    com->write_rs232(0xaa);

    In der Klasse fmain_window wird die instanz com der Klasse rs232 erzeugt.
    Klasse fmain_window:
    com = new rs232;
    com->baudrate = 56000;
    com->comport = "com1";
    com->timeout = com_timeout;

    Oder verstehe ich da irgendetwas falsch?



  • hermes schrieb:

    class rs232; // Forward-Deklaration
    Ist das das gleiche wie extern?

    Nein. Das ist nur dafür da, um ein include auf den Header von rs232 zu vermeiden. Du könntest auch den header per include
    hinzufügen, wenn Du das aber konsequent machst, bekommst Du irgendwann eine Riesenhierarchie von includes und damit lange Kompilier-
    zeiten.
    Außerdem kannst Du mit einer Forward-Deklaration gegenseitige includes auflösen.

    hermes schrieb:

    Der Konstruktor übergibt einen Zeiger rs232* RS232, damit der Zeiger bekannt ist die Forward-Deklaration (könnte man nicht auch den Header der Klasse rs232
    includieren?)

    Ja und s.o.

    hermes schrieb:

    Ich kann dann aber immer noch nicht auf das Object com der Klasse rs232
    das in einer anderen Klasse (fmain_window)instanziert wurde zugreifen oder?

    Na klar. Du musst ja nur genau diese Instanz im Konstruktor übergeben:

    // z.B. von fmain_window aus:
      fthresholds = Tfthresholds(Application, com);
    

    Ich hoffe, Du hast das jetzt verstanden. Auf jeden Fall kann es nicht schaden, Dir vielleicht mal ein paar Grundlagen zur
    Objektorientierung und zu Zeigern anzuschauen.

    Gruß,

    Alexander


Anmelden zum Antworten