Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Probleme beim erstellen von VarArrays in Klasse
GR-Thunderstorm - Di 01.11.11 11:32
Titel: Probleme beim erstellen von VarArrays in Klasse
Hey!
Ich habe mich nach vielen Jahren Delphi-Abstinenz nun doch wieder mit meinem Delphi7 Enterprise auseinander gesetzt und möchte ein kleines Programm schreiben.
Damit es auch übersichtlich bleibt, möchte ich einige Functions / Procedures in eine andere Unit auslagern.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| unit MainUnit;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Math, ExtCtrls, Buttons, ComCtrls, Mask, StrUtils;
type TForm1 = class(TForm) Button2: TButton; procedure Button2Click(Sender: TObject); private public end;
var Form1: TForm1;
implementation
uses Functions;
{$R *.dfm}
procedure TForm1.Button2Click(Sender: TObject); var Float: Real; begin Float:=Bessel_1(2.405,100); ShowMessage(FloatToStr(Float)); end;
end. |
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| unit Functions;
interface uses Graphics, SysUtils, Math, MainUnit;
implementation
function Factorial_2(Int: Integer) : Extended; begin if (Int <2) then Result := 1 else Result := Int*Factorial_2(Int-2); end;
function Bessel_1(X: Extended; Steps: Integer) : Extended; var i: Integer; PreResult: Real; begin PreResult:=0; for i:=1 to Steps do begin PreResult:= PreResult + Power(-1, i+1 mod 2)*Power(X,i*2-1) / (Power(Factorial_2((i*2)-2),2)*i*2); end;
Result:=PreResult;
end;
end. |
Wenn ich das Programm starten will, springt er in der MainUnit an die Stelle, wo Bessel_1 aufgerufen werden soll und meckert: 'Undeclared identifier: Bessel_1'
Was mache ich denn falsch? :(
EDIT: Problemstellung hat sich geändert. :) Siehe weiter unten.
jaenicke - Di 01.11.11 11:47
Delphi weiß nicht, dass die Funktion für andere Units sichtbar sein soll.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| unit Functions;
interface
uses Graphics, SysUtils, Math, MainUnit;
function Factorial_2(Int: Integer): Extended; function Bessel_1(X: Extended; Steps: Integer): Extended;
implementation
function Factorial_2(Int: Integer): Extended; begin if (Int < 2) then Result := 1 else Result := Int * Factorial_2(Int - 2); end;
function Bessel_1(X: Extended; Steps: Integer): Extended; var i: Integer; PreResult: Real; begin PreResult := 0; for i := 1 to Steps do begin PreResult := PreResult + Power(-1, i + 1 mod 2) * Power(X, i * 2 - 1) / (Power(Factorial_2((i * 2) - 2), 2) * i * 2); end;
Result := PreResult; end;
end. |
Nebenbei: Unterstriche in Funktionsnamen sind kein guter Stil. ;-)
GR-Thunderstorm - Di 01.11.11 21:41
Danke, das hat funktioniert! :zustimm:
Geht es auch irgendwie, dass ich alle globalen Variablen in eine externe Unit auslagere?
jaenicke - Di 01.11.11 21:49
Verwende möglichst niemals globale Variablen. Das ist sehr schlechter Stil, da es die Übersicht enorm verringert...
Du kannst stattdessen z.B. Sachen in Klassen kapseln, je nachdem was du machst.
GR-Thunderstorm - Mo 07.11.11 21:37
Soweit so gut, ich wollte eine eigene Klasse erstellen, um in dieser einige Werte berechnen zu lassen.
Hier zunächst der Code:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77:
| type Mue = class private Precision: Integer; Z0: Variant; ffg: Variant; MueIm: Variant; MueRe: Variant;
procedure Assign_ffg(f: Variant); procedure Assign_Z(Z: Variant);
public procedure Create();
property Z: Variant read Z0 write Assign_Z; property f_fg: Variant read ffg write Assign_ffg; property Im: Variant read MueIm; property Re: Variant read MueRe; end;
implementation
uses Functions;
procedure TSensor.LO(Z:Integer); begin Lift:=Z; end;
procedure Mue.Create(); begin Precision:=160; self.Z0:=VarArrayCreate([0,0],VarVariant); self.ffg:=VarArrayCreate([0,0],VarVariant); self.MueIm:=VarArrayCreate([0,0],VarVariant); self.MueRe:=VarArrayCreate([0,0],VarVariant); end;
procedure Mue.Assign_Z(Z: Variant); var Index,i: Integer; f: Extended; begin
f:=Z*Z;
for i:=0 to VarArrayHighBound(Z0,1)-1 do begin if Z > Z0[i] and Z < Z0[i+1] then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision));
end;
procedure Mue.Assign_ffg(f: Variant); var Index,i: Integer; Z: Extended; begin
Z:=sqrt(f);
for i:=0 to VarArrayHighBound(ffg,1)-1 do begin if Z > Z0[i] and Z < Z0[i+1] then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision));
end; |
An besagter Stelle erzeugt mein Programm jedes mal einen Fehler, wenn ich eine Variable vom Typ Mue deklariere und die Create-Funktion aufrufe. Auf diese Weise habe ich allerdings schon etliche Variant-Arrays erstellt und nie gab es Probleme! Muss ich in einer Klasse anders verfahren, um VarArrayCreate anwenden zu können?
bummi - Mo 07.11.11 21:45
Mach aus
mal
achja ... Klammern fehlen auch
Delphi-Quelltext
1:
| if (Z > Z0[i]) and (Z < Z0[i+1]) then Index:=i; |
GR-Thunderstorm - Mo 07.11.11 21:57
Das ändert leider nichts. :( Jetzt erzeugt er schon bei
einen Fehler.
EDIT:
Soeben beschriebenes konnte ich korrigieren, indem ich folgendes gemacht habe:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| type Mue = class private Precision: Integer; Z0: Variant; ffg: Variant; MueIm: Variant; MueRe: Variant;
procedure Assign_ffg(f: Variant); procedure Assign_Z(Z: Variant); procedure SetPrecision(X: Integer);
property Pr: Integer read Precision write SetPrecision;
public constructor Create();
property Z: Variant read Z0 write Assign_Z; property f_fg: Variant read ffg write Assign_ffg; property Im: Variant read MueIm; property Re: Variant read MueRe; end;
implementation
uses Functions;
procedure TSensor.LO(Z:Integer); begin Lift:=Z; end;
constructor Mue.Create(); begin self.Pr:=160; self.Z:=VarArrayCreate([0,0],varVariant); self.ffg:=VarArrayCreate([0,0],varVariant); self.MueIm:=VarArrayCreate([0,0],varVariant); self.MueRe:=VarArrayCreate([0,0],varVariant); end; |
Selbiges wollte ich mit Z machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59:
| procedure Mue.SetPrecision(X: Integer); begin Precision:=X; end;
procedure Mue.Assign_Z(Z: Variant); var Index,i: Integer; f: Extended; begin
if Z = VarArrayCreate([0,0],varVariant) then begin Z:=VarArrayCreate([0,0],varVariant); end else begin
f:=Z*Z;
for i:=0 to VarArrayHighBound(Z0,1)-1 do begin if Z > Z0[i] and Z < Z0[i+1] then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision)); end;
end;
procedure Mue.Assign_ffg(f: Variant); var Index,i: Integer; Z: Extended; begin
Z:=sqrt(f);
if f = VarArrayCreate([0,0],varVariant) then begin ffg:=VarArrayCreate([0,0],varVariant); end else begin
for i:=0 to VarArrayHighBound(ffg,1)-1 do begin if Z > Z0[i] and Z < Z0[i+1] then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision));
end;
end; |
platzwart - Mo 07.11.11 22:10
"einen Fehler", das ist ja äußerst präzise und nun weiß jeder, was das sein könnte... ;)
Blawen - Mo 07.11.11 22:20
GR-Thunderstorm hat folgendes geschrieben : |
Das ändert leider nichts... Precision:=160;
einen Fehler. |
1. Dieser Fehler wird sicher genauer ausgegeben.
2. Vermutlich wird es daran liegen, dass Precision als "Private" deklariert wurde.
Blawen - Mo 07.11.11 22:25
[OT]Stochern im Nebel :roll: [/OT]
GR-Thunderstorm - Mo 07.11.11 22:27
Blawen hat folgendes geschrieben : |
[OT]Stochern im Nebel :roll: [/OT] |
Titel abgeändert. ;)
Blawen - Mo 07.11.11 22:34
Zitat: |
'Invalid variant operation' |
Ist schon mal eine brauchbare Aussage.
Allerdings wäre es von Vorteil, wenn auch wir wüssten, wie Deine aktuelle "Baustelle" aussieht (QT-Auzug)
GR-Thunderstorm - Mo 07.11.11 22:38
Je nach Art der Ausführung entweder hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| constructor Mue.Create(); begin self.Pr:=160; self.Z:=VarArrayCreate([0,0],varVariant); self.ffg:=VarArrayCreate([0,0],varVariant); self.MueIm:=VarArrayCreate([0,0],varVariant); self.MueRe:=VarArrayCreate([0,0],varVariant); end;
procedure Mue.Assign_Z(Z: Variant); var Index,i: Integer; f: Extended; begin
if Z = VarArrayCreate([0,0],varVariant) then begin Z0:=VarArrayCreate([0,0],varVariant); end else begin
f:=Z*Z;
for i:=0 to VarArrayHighBound(Z0,1)-1 do begin if (Z > Z0[i]) and (Z < Z0[i+1]) then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision)); end;
end; |
Oder hier:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| constructor Mue.Create(); begin self.Pr:=160; self.Z0:=VarArrayCreate([0,0],varVariant); self.ffg:=VarArrayCreate([0,0],varVariant); self.MueIm:=VarArrayCreate([0,0],varVariant); self.MueRe:=VarArrayCreate([0,0],varVariant); end; |
Edit:
Ich habe das ganze etwas abgewandelt, um die Fehlerhafte If-Anweisung zu vermeiden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110:
| type Mue = class private Precision: Integer; Z0: Variant; ffg: Variant; MueIm: Variant; MueRe: Variant; InCreation: Boolean;
procedure Assign_ffg(f: Variant); procedure Assign_Z(Z: Variant); procedure SetPrecision(X: Integer); procedure Assign_MueIm(Mue: Variant); procedure Assign_MueRe(Mue: Variant);
property Pr: Integer read Precision write SetPrecision;
property CreateMueIm: Variant read MueIm write Assign_MueIm; property CreateMueRe: Variant read MueRe write Assign_MueRe;
public constructor Create();
property Z: Variant read Z0 write Assign_Z; property f_fg: Variant read ffg write Assign_ffg; property Im: Variant read MueIm; property Re: Variant read MueRe; end;
implementation
uses Functions;
procedure TSensor.LO(Z:Integer); begin Lift:=Z; end;
constructor Mue.Create(); begin InCreation:=true; self.Pr:=160; self.Z:=VarArrayCreate([0,0],varVariant); self.f_fg:=VarArrayCreate([0,0],varVariant); self.CreateMueIm:=VarArrayCreate([0,0],varVariant); self.CreateMueRe:=VarArrayCreate([0,0],varVariant); InCreation:=false end;
procedure Mue.SetPrecision(X: Integer); begin Precision:=X; end;
procedure Mue.Assign_ffg(f: Variant); var Index,i: Integer; Z: Extended; begin
if not InCreation then begin Z:=sqrt(f);
for i:=0 to VarArrayHighBound(ffg,1)-1 do begin if (Z > Z0[i]) and (Z < Z0[i+1]) then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision)); end else ffg:=VarArrayCreate([0,0],VarVariant); end;
procedure Mue.Assign_Z(Z: Variant); var Index,i: Integer; f: Extended; begin
if not InCreation then begin f:=Z*Z;
for i:=0 to VarArrayHighBound(Z0,1)-1 do begin if (Z > Z0[i]) and (Z < Z0[i+1]) then Index:=i; end;
VarArrayInsert(Z0,Index,Z); VarArrayInsert(ffg,Index,f); VarArrayInsert(MueIm,Index,MueEffIm(Z,Precision)); VarArrayInsert(MueRe,Index,MueEffRe(Z,Precision));
end else Z0:=VarArrayCreate([0,0],VarVariant); end;
procedure Mue.Assign_MueIm(Mue: Variant); begin MueIm:=VarArrayCreate([0,0],varVariant); end;
procedure Mue.Assign_MueRe(Mue: Variant); begin MueRe:=VarArrayCreate([0,0],varVariant); end; |
Wenn ich einzelne Zeilen aus dem constructor weg-kommentiere, kann ich entsprechend andere Stellen ausführen lassen und jedes mal kommt beim Aufruf von VarArrayCreate die gleiche Fehlermeldung. :(
jaenicke - Mo 07.11.11 23:00
Vermutung:
Du rufst den Konstruktor fälschlicherweise so auf:
Delphi-Quelltext
1: 2: 3: 4:
| var xyz: TMue; begin xyz.Create; |
Self ist dann im Konstruktor gar nicht definiert, da es die uninitialisierte Variable xyz ist. Und deshalb knallt es.
Nebenbei:
Es ist Konvention, dass ein Klassenname
immer mit T beginnt.
GR-Thunderstorm - Mo 07.11.11 23:04
Moderiert von
Narses: Komplett-Zitat des letzten Beitrags entfernt.
Hmm nunja, es wird skuriler:
Ich habe herausgefunden, dass diese Zeile KEINEN Fehler verursacht:
Delphi-Quelltext
1:
| ffg:=VarArrayCreate([0,0],VarVariant); |
Wegen der Konvention: Das werde ich dann mal abändern. :)
Edit:
Ich habe den Fehler gefunden. >.< Ich wusste erst nicht so genau, was Jaenicke mir mit dem Post sagen wollte. ^^
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| var Test: TMue; begin Test.Create(); end;
var Test: TMue; begin Test:=TMue.Create(); end; |
Das erklärt zwar nicht, wieso auf "ffg" zugegriffen werden konnte und auf "Z0" nicht, aber nun klappt alles wunderbar. :)
Vielen Dank für die Hilfe (und vor allem Geduld! :D) an euch alle!
jaenicke - Di 08.11.11 06:51
GR-Thunderstorm hat folgendes geschrieben : |
Das erklärt zwar nicht, wieso auf "ffg" zugegriffen werden konnte und auf "Z0" nicht |
Reiner Zufall. ;-)
Da du auf die Methode Create des (uninitialisierten) Objekts statt auf den Konstruktor der Klasse zugegriffen hast, hast du dort auf zufällige Stellen im Speicher zugegriffen. Und das knallt eben mal und mal nicht sofort.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!