Eigenschaften einer Klasse --> Fehlermeldung
-
hab eine Klasse in der ich Eigenschaften verwende. Ich erhalte dann beim Zugriff folgende Fehlermeldung:
[C++ Fehler] algorith.cc(422): E2328 Klassen mit Eigenschaften dürfen nicht über ihren Wert kopiert werden.
Meine Klasse hab ich so definiert:
class Messwerte { private: TDateTime datum; TDateTime uhrzeit; float temperatur; float phwert; float redoxwert; float drehzahl; float drehmoment; float volumen; float volumenstrom; void SetDatum(TDateTime datum) {this->datum = datum;} void SetUhrzeit(TDateTime uhrzeit) {this->uhrzeit = uhrzeit;} void SetTemperatur(float temperatur) {this->temperatur = temperatur;} void SetPhwert(float phwert) {this->phwert = phwert;} void SetRedoxwert(float redoxwert) {this->redoxwert = redoxwert;} void SetDrehzahl(float drehzahl) {this->drehzahl = drehzahl;} void SetDrehmoment(float drehmoment) {this->drehmoment = drehmoment;} void SetVolumen(float volumen) {this->volumen = volumen;} void SetVolumenstrom(float volumenstrom) {this->volumenstrom = volumenstrom;} TDateTime GetDatum() {return datum;} TDateTime GetUhrzeit() {return uhrzeit;} float GetTemperatur() {return temperatur;} float GetPhwert() {return phwert;} float GetRedoxwert() {return redoxwert;} float GetDrehzahl() {return drehzahl;} float GetDrehmoment() {return drehmoment;} float GetVolumen() {return volumen;} float GetVolumenstrom() {return volumenstrom;} public: Messwerte(); __property TDateTime Datum = {read=GetDatum, write=SetDatum}; __property TDateTime Uhrzeit = {read=GetUhrzeit, write=SetUhrzeit}; __property float Temperatur = {read=GetTemperatur, write=SetTemperatur}; __property float Phwert = {read=GetTemperatur, write=SetTemperatur}; __property float Redoxwert = {read=GetTemperatur, write=SetTemperatur}; __property float Drehzahl = {read=GetTemperatur, write=SetTemperatur}; __property float Drehmoment = {read=GetTemperatur, write=SetTemperatur}; __property float Volumen = {read=GetTemperatur, write=SetTemperatur}; __property float Volumenstrom = {read=GetTemperatur, write=SetTemperatur}; };
hier der Zugriff in einer Methode der Form (frmHO):
void TfrmHO::ErfasseMessdaten(int AnzahlMesswerte) { messwerte.Datum = Date(); messwerte.Uhrzeit = Time(); messwerte.Temperatur = emko->Istwert; vMesswerte.reserve(AnzahlMesswerte); //vMesswerte ist ein Vektor den ich im Header der Form als private deklariert hab also: std::vector<Messwerte>vMesswerte; vMesswerte.push_back(messwerte); }
ein Timer ruft die Funktion dann immer wieder auf.
-
Siehe hier
-
ich finde dort keine Lösung für mein Problem.
-
du brauchst einen Kopierkonstuktor und der ist auf der verlinkten Seite durchaus beschrieben
-
rudpower schrieb:
Meine Klasse hab ich so definiert:
/* Redundanzparty! */
Wenn deine Klasse lediglich ein Verbund von Daten ist, mach doch eine Struktur mit öffentlichen Feldern daraus. Es gibt exakt keinen Grund, warum dieses Konstrukt eine Klasse sein sollte.
Properties sind überhaupt nur sinnvoll, wenn du Kapselung oder Serialisierung mittels RTTI willst, und selbst dann könntest du viel Redundanz vermeiden, indem du einfach das Feld als Getter und ggf. Setter angibst:
__property float Volumen = { read = volumen, write = volumen };
-
also am besten gar keine Eigenschaften verwenden? Hatte das mit den Eigenschaften nur in einem Buch gelesen und fand es einfacher als immer Get und Set aufzurufen.
Also kann ich es so machen:Header: Messwerte.h:
struct Messwerte { TDateTime datum; TDateTime uhrzeit; float temperatur; float phwert; float redoxwert; float drehzahl; float drehmoment; float volumen; float volumenstrom } messwerte;
Zugriff über Form HO.h:
void TfrmHO::ErfasseMessdaten(int AnzahlMesswerte) { messwerte.datum = Date(); messwerte.uhrzeit = Time(); messwerte.Temperatur = emko->Istwert; vMesswerte.reserve(AnzahlMesswerte); vMesswerte.push_back(messwerte); }
So wär es natürlich einfacher und spart ne Menge Code.
Sollte ich die Struktur vielleicht gar nicht in eine andere Date auslagern? Ich könnte sie ja auch in private der Form deklarieren? Wie und wo initialisier ich messwerte am besten?
-
rudpower schrieb:
also am besten gar keine Eigenschaften verwenden?
Die VCL-Properties sind nunmal nicht aus dem C++ Standard, sondern aus Delphi übernommen. Deshalb passen sie nicht sehr gut zum C++ Standard und lohnen sich nur wenn du wenn du die VCL-Möglichkeiten nutzt und brauchst.
Hatte das mit den Eigenschaften nur in einem Buch gelesen und fand es einfacher als immer Get und Set aufzurufen.
Das Wissen um den Aufbau der Properties ist im Builder schon wichtig, und es verkürzt ja den Quellcode auch. Nur verschleiern Properties eben auch ein paar Eigenheiten, und reine Getter/Setter sind einfach sauberer und passen besser in C++ .
Also kann ich es so machen:
...
So wär es natürlich einfacher und spart ne Menge Code.
Sollte ich die Struktur vielleicht gar nicht in eine andere Date auslagern? Ich könnte sie ja auch in private der Form deklarieren? Wie und wo initialisier ich messwerte am besten?Wie schon gesagt brauchst du bei einer reinen Variablen-Komposition wie deinem Messwerte keine Getter/Setter und damit auch keine Properties. Ist einfacher und übersichtlicher.
Ich würde trotzdem der Struktur (struct oder class ist fast dasselbe) noch einen Standard-Konstruktor mitgeben, um alle PODs (also bei dir die floats) ordentlich mit 0 zu initialisieren.bis bald
akari
-
ja ok, danke. Also sollte ich das auch in eine externe header auslagern?
-
Hallo
Notwendig ist es nicht, empfehlenswert schon.
bis bald
akari
-
ok hab das mal geändert. Hier mein Quellcode:
aus Messwerte.h:
struct Messwerte { Messwerte(); TDateTime datum; TDateTime uhrzeit; float temperatur; float phwert; float redoxwert; float drehzahl; float drehmoment; float volumen; float volumenstrom; };
aus Messwerte.cpp:
Messwerte::Messwerte() : temperatur(0), phwert(0), redoxwert(0), drehzahl(0), drehmoment(0), volumen(0), volumenstrom(0) {}
aus HO.h (meiner Anwendung):
class TfrmHO : public TForm { __published: // Von der IDE verwaltete Komponenten TLMDGroupBox *LMDGroupBox1; TTimer *timMessreihen; TLMDGroupBox *LMDGroupBox2; TLMDButton *btnStart; TLMDButton *btnStop; TLMDLabeledMaskEdit *txtIntervallMessreihen; TLMDLabeledMaskEdit *txtAnzahlMessreihen; TLMDButton *btnAusgabe; TStringGrid *grdMesswerte; void __fastcall btnStartClick(TObject *Sender); void __fastcall btnStopClick(TObject *Sender); void __fastcall timMessreihenTimer(TObject *Sender); void __fastcall btnAusgabeClick(TObject *Sender); private: // Anwender-Deklarationen Messwerte messwerte; std::vector<Messwerte>vMesswerte; public: // Anwender-Deklarationen __fastcall TfrmHO(TComponent* Owner); void ErfasseMesswerte(); };
HO.cpp:
void TfrmHO::ErfasseMesswerte() { messwerte.datum = Date(); messwerte.uhrzeit = Time(); messwerte.temperatur = rand(); //erst mal nur rand Werte, später dann aus Messgerät messwerte.phwert = rand(); messwerte.redoxwert = rand(); messwerte.drehzahl = rand(); messwerte.drehmoment = rand(); messwerte.volumen = rand(); messwerte.volumenstrom = rand(); vMesswerte.push_back(messwerte); }
Gibts Verbesserungsvorschläge? Ist das ok so?
-
Jetzt noch durchweg englische Nomenklatur, dann siehts ganz gut aus.
Im Übrigen speichert ein TDateTime-Objekt sowohl Datum als auch Uhrzeit (rate mal, warum es so heißt). Zwei davon zu haben ist also nicht notwendig.