Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   TComponents handhaben (https://www.delphipraxis.net/181903-tcomponents-handhaben.html)

Mikkey 16. Sep 2014 15:03

TComponents handhaben
 
Es geht zwar um ein Projekt in C++ (XE), aber ich denke/gehe davon aus, dass das Verhalten in Delphi dasselbe sein sollte.

Da ich Interfaces (anstelle von Sätzen von Rückruffunktionen) verwenden möchte, sind alle eigenen Klassen von TComponent abgeleitet.

Ich verstehe die hier mit der Suche gefundenen Beiträge so, dass beim Zerstören eines TComponent-Objekts (owner) auch die TComponents (member) zerstört werden, die mit der Angabe owner erzeugt wurden:

Code:
TOwner <-- TComponent
TMember <-- TComponent
Delphi-Quellcode:
var owner: TOwner; member: TMEmber;
...
owner = TOwner.Create(0);
member = TMember.Create(owner);
...
owner.Free();
Ich würde eigentlich erwarten, dass beim Ausführen der letzten Zeile auch der Destruktor von TMember durchlaufen wird. Tatsächlich tut er das aber nur, wenn im Destruktor von TOwner der Aufruf
Delphi-Quellcode:
DestroyComponents();
enthalten ist.

Die Komponenten sind keine Controls.

Wäre nett, wenn mir jemand ein "ISSO!" oder "müsste eigentlich klappen" geben könnte - möglichst nicht beides ;)

mjustin 16. Sep 2014 15:17

AW: TComponents handhaben
 
Zitat:

Zitat von Mikkey (Beitrag 1272783)
Ich würde eigentlich erwarten, dass beim Ausführen der letzten Zeile auch der Destruktor von TMember durchlaufen wird. Tatsächlich tut er das aber nur, wenn im Destruktor von TOwner der Aufruf
Delphi-Quellcode:
DestroyComponents();
enthalten ist.

Im Destruktor muss inherited (Destroy) aufgerufen werden. Andernfalls wird es auch in Delphi nicht wie erwartet funktioniere. Der Destruktor wird (in Delphi) mit override deklariert.

Hope this helps,

DeddyH 16. Sep 2014 15:29

AW: TComponents handhaben
 
Wenn man die Klassenvervollständigung nutzt, geschieht das sogar automatisch ;)

[edit] Um etwas genauer zu werden: ich habe mal diese Klassen deklariert
Delphi-Quellcode:
type
  TOwner = class(TComponent)
  public
    destructor Destroy; override;
  end;

  TMember = class(TComponent)
  public
    destructor Destroy; override;
    procedure SayHello;
  end;
Nun den Cursor irgendwo in der TOwner-Klasse platziert und CTRL + SHIFT + C gedrückt, dann den Cursor in die TMember-Klasse und dasselbe noch einmal. Ich poste hier mal den gesamten Source, die ShowMessage-Aufrufe sind von mir, der Rest wurde automatisch generiert:
Delphi-Quellcode:
{ TOwner }

destructor TOwner.Destroy;
begin
  ShowMessage('Owner wird freigegeben');
  inherited;
end;

{ TMember }

destructor TMember.Destroy;
begin
  ShowMessage('Member wird freigegeben');
  inherited;
end;

procedure TMember.SayHello;
begin
  ShowMessage('Hallo vom Member');
end;
Nun noch ein kleiner Test:
Delphi-Quellcode:
procedure TFormTest.Button1Click(Sender: TObject);
var
  Owner: TOwner;
  Member: TMember;
begin
  Owner := TOwner.Create(nil);
  try
    Member := TMember.Create(Owner);
    Member.SayHello;
  finally
    Owner.Free;
  end;
end;
[/edit]

Mikkey 16. Sep 2014 16:11

AW: TComponents handhaben
 
Leider hilft mir beides nicht weiter, denn

a) gibt es in C++ kein "inherited", der Destruktor der Basisklasse wird ohnehin implizit aufgerufen (lässt sich auch aus Vorsatz nicht verhindern)
b) Strg+Shift+C tut im C++Builder ... nichts

Glücklicherweise führt der manuell eingefügte
Code:
DestroyComponents();
nicht zu einem Fehler, ich hätte darauf nur gern verzichtet, wenn TComponent das doch selbst machen soll.

Uwe Raabe 16. Sep 2014 16:22

AW: TComponents handhaben
 
Zitat:

Zitat von Mikkey (Beitrag 1272783)
Es geht zwar um ein Projekt in C++ (XE), aber ich denke/gehe davon aus, dass das Verhalten in Delphi dasselbe sein sollte.

Das scheint dann aber ganz offensichtlich nicht der Fall zu sein, obwohl ich das eigentlich auch erwartet hätte.

Mikkey 16. Sep 2014 16:34

AW: TComponents handhaben
 
Dann nehme ich wenigstens mit, dass es in Delphi das tut, was ich erwarte :?

Der schöne Günther 16. Sep 2014 17:13

AW: TComponents handhaben
 
Dann zeig doch mal ein bisschen Code- Ich kann das nicht nachvollziehen: Wie auch in Delphi ist die Reihenfolge
  1. ~TOwner
  2. Geerbter TComponent-Destruktor: Ruft TComponent.DestroyComponents() auf
  3. Diese Methode zerstört die TMember-Instanz
  4. ~TMember

Code:
#include <vcl.h>
#include <windows.h>

#pragma hdrstop
#pragma argsused

#include <tchar.h>
#include <stdio.h>

class TOwner: public TComponent {
   public:
      __fastcall virtual ~TOwner() {
         (void)0; // Haltepunkt. Wird erreicht.
      }

      __fastcall virtual TOwner(TComponent* AOwner): TComponent(AOwner){};
};

class TMember: public TComponent {
   public:
      __fastcall virtual ~TMember() {
         (void)0; // Haltepunkt. Wird erreicht.
      }

      __fastcall virtual TMember(TComponent* AOwner): TComponent(AOwner){};
};

int _tmain(int argc, _TCHAR* argv[])
{

   TOwner *myOwner = new TOwner(NULL);
   TMember *myMember = new TMember(myOwner);
   myOwner->Free();
   return 0;
}

Mikkey 16. Sep 2014 17:45

AW: TComponents handhaben
 
Komischerweise stoppt der Debugger an den (void)0-Zeilen. Nachdem ich das betreffende Projekt wieder geladen habe und einen "DestroyComponent" auskommentiert habe, hat er im Destruktor der Member-Klasse ebenfalls angehalten. Die vorher generierten "nicht-gelöscht-Debugausgaben" sind ebenfalls nicht mehr da.

Dafür gibt's jetzt andere Fehler, das muss ich mir erstmal ansehen.

Das ganze Projekt kann ich aus naheliegenden Gründen hier nicht einstellen, Teile wäre erst sinnvoll, wenn ich weiß, welche gebraucht werden.

Der schöne Günther 16. Sep 2014 18:02

AW: TComponents handhaben
 
Ich verstehe nicht
  • Wie, der Debugger stoppt? Exception? Mit F7 kommst du eigentlich danach in den übergeordneten Destruktor ~TComponent...
  • Welches DestroyComponent auskommentiert? Die Delphi RTL verändert? DestroyComponents musst du nicht selbst aufrufen...
  • Welche C++ Builder-Version ist das denn überhaupt?

sx2008 16. Sep 2014 21:24

AW: TComponents handhaben
 
Zitat:

Zitat von Mikkey (Beitrag 1272783)
Da ich Interfaces (anstelle von Sätzen von Rückruffunktionen) verwenden möchte, sind alle eigenen Klassen von TComponent abgeleitet.

Hier fängt das Problem schon an.
Nur weil man Interfaces implementieren möchte bedeutet das noch lange nicht dass man von
Delphi-Quellcode:
TComponent
ableiten sollte.
Interfaces und TComponent haben völlig unterschiedliche Konzepte bezüglich der Lebenszeit der Objekte.
Während Interfaces auf Referenzzählung setzen werden beim Tod eines "Königs" (die oberste Komponente, meist ein Formular oder Datenmodul) alle Untertanen sowie deren Untertanen destroyed.
Komponenten bilden eine Baumstruktur wenn man einen Owner angibt.

Weil Borland aber ActiveX-Controls unterstützen wollte musste man beide Konzepte unter einen Hut bringen.
Das funktioniert aber naturgemäß nur unter Schwierigkeiten.

Es gibt aber einige andere Basisklassen die ebenfalls
Delphi-Quellcode:
IInterface
bzw.
Delphi-Quellcode:
IUnknown
implementieren und besser als Ausgangspunkt geeignet sind: TAutoIntfObject,TAutoObject,TComObject,TInterfaced Object
Je nach Anwendungszweck wählt man die passende Basisklasse.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:11 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz