[gelöst]Instanzen eines unbest. Types ->Falscher Constructor

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

[gelöst]Instanzen eines unbest. Types ->Falscher Constructor

Beitrag von MAC »

Hallo liebes Lazarusforum,

Ich möchte Instanzen einer Klasse erstellen. Allerdings von einer unbestimmten Instanz.
Dabei hab ich das Problem das der Falsche Constructor aufgerufen wird (ich schätze mal der von TObject). Ich habe einen kleinen Beispiel Code gebastelt.

Es gibt eine Klasse TSomeClass mit einem Constructor in dem der wert fSomeValue gesetzt wird.
Erstellt man jetzt die Klasse normal ist fSomeValue = 9999;
Nimmt man jetzt aber eine Variable des Types TClass . und ruft eine Funktion auf in der Dynamisch das passende Objekt erstellt wird: So wird der Constructor nicht mehr aufgerufen.

Das ist ein simples Programm was ihr schnell testen könnt.
Kommt bei euch das gleiche raus wie bei mir?
Wisst ihr, wie ich das Problem umgehen kann?

Vielen Dank :)

Code: Alles auswählen

 
AUSGABE:
9999
0
 
 


Code: Alles auswählen

 
program project1;
 
uses classes;
 
type
 
  { TSomeClass }
 
  TSomeClass = class(TObject)
  private
    fSomeValue:integer;
  public
    Constructor Create;
  end;
 
{ TSomeClass }
 
constructor TSomeClass.Create;
begin
fSomeValue := 9999;
end;
 
{ CODE }
 
var
  c1,c2:TSomeClass;
  ac:TClass;
 
function ImporantFunction(aClass:TClass):TObject;
begin
result := aClass.Create;
end;
 
begin
c1 := TSomeClass.Create;
aC := TSomeClass;
c2 := TSomeClass(ImporantFunction(aC));
writeln(c1.fSomeValue);
writeln(c2.fSomeValue);
readln;
end.
Zuletzt geändert von MAC am Fr 24. Okt 2014, 21:22, insgesamt 1-mal geändert.

Code: Alles auswählen

Signatur := nil;

Michl
Beiträge: 2365
Registriert: Di 19. Jun 2012, 12:54

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von Michl »

MAC hat geschrieben:Kommt bei euch das gleiche raus wie bei mir?
Wisst ihr, wie ich das Problem umgehen kann?
Gleiches Verhalten bei mir. Weiss aber nicht, ob das überhaupt funktionieren kann, da imho der Compiler wahrscheinlich das TClass.Create einfach übersetzt.

Umständlich, aber es funktioniert bei mir:

Code: Alles auswählen

function ImporantFunction(aClass: TClass): TObject;
begin
  case aClass.ClassName of
    'TSomeClass': Result := TSomeClass.Create;
  end;
//  result := aClass.Create;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von MAC »

Danke fürs Testen,
Das wäre natürlich möglich, nur leider bringt mir das nichts, weil ich diese Klassen komplett Generisch erstellen will (Der benutzer kann bestimmte Klassen zu Laufzeit Definieren, und diese werden dann später erzeugt).

Code: Alles auswählen

Signatur := nil;


MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von MAC »

Danke, der zweite Beitrag bei Stackoverflow ist genau das, was ich brauche.
Leider ist der Dort verwendete Weg nur für Delphi möglich (die unit rtti, gibt es bei Lazaurs nicht. Ich denke mal stattdessen gibt es typinfo).

Mit TypeInfo kann ich zwar die Procedure 'Create' suchen. Da die aber nicht published ist, liefert es mir nil zurück.

Ich probiere da noch etwas weiter und versuch morgen zu schreiben, falls ich was neues entdecke...

Code: Alles auswählen

Signatur := nil;

Socke
Lazarusforum e. V.
Beiträge: 2861
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von Socke »

Der Konstruktor von TObject ist statisch, wird also von abgeleiteten Klassen nicht überschrieben.
Lösung:

Code: Alles auswählen

type
tmyc = class(TObject)  // Basis-Klasse
public
  constructor Create; virtual; // Virtueller Konstruktor
end;
tmycClass = class of tmyc; // jetzt wird der virtuelle Konstruktor verwendet, also auch die Konstruktoren der abgeleiteten Klassen
tmyc2 = class(tmyc)
  constructor Create; override;
end;
// [...]
 
function InitObjects(aclass: tmycClass): tmyc;
begin
  Result := aClass.Creat;
end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von MAC »

Danke, damit lässt sich was anfangen...
Nur müsste ich jetzt jede Klasse von einem TObject mit virtuellem Konstruktor ableiten...
Bzw ich kann auch jede beliebige klasse als Tmyc Parsen und wenn sie einen virtuellen Konstruktor hat scheint es zu gehen andernfalls bekomm ich eine Fehlermeldung...
Ich werd mir das noch weiter anschauen und sollte ich etwas eleganteres finden schreib ich das hier rein :)

Code: Alles auswählen

Signatur := nil;

Soner
Beiträge: 417
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von Soner »

Schau mal LCL's Application.CreateForm-Prozedur, dort wird das gemacht was du willst:
LCLs TApplication.CreateForm(InstanceClass: TComponentClass; out Reference);

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: Instanzen eines unbestimmten Types -> Falscher Construct

Beitrag von MAC »

Ich habe das jetzt gelöst.
Mehr oder weniger zufrieden,

Dazu hab ich den Ansatz aus viewtopic.php?f=10&t=8178&p=72416#p72416 verwendet.
Das Ergebnis ist dann eine Intannz eines unbestimmten Types, allerdings brauch man dafür 2 Informationen.
1. Die Klasse muss in einer Variable vom Typ TClass stehen
2. Der klassenconstructor muss als pointer (und hier ohne Parameter) vorhanden sein.

Die Umsetzung erfolgte mit einer Liste in der die 2 Datenpaare für jede Klasse gespeichert sind. Nur muss am anfang des Programms einmal jede Klasse die benutzt werden will registriert werden.

Code: Alles auswählen

Signatur := nil;

Antworten