Forum: PC-Programmierung Status mit "get"-Methode abfragen oder direkt die Variable auslesen


von zitter_ned_aso (Gast)


Lesenswert?

Hallo,


erst mal zur Ausgangslage: Ein Programm, das GUI besitzt, startet einen 
Thread, der nebenbei (ohne GUI zu blockineren) die Anzeige z.B. x-mal 
pro y-Zeitheiten aktualisiert.

Den Verlauf steuert die (private) Klassenvariable "bool running".  Man 
sagt ja dass auf die Klassenvariablen per "set"/"get"-Methoden 
zugegriffen werden soll.

Also bekommt die Klasse noch zwei public-Methoden:
1
void set_running(bool new_val);
2
bool get_running();
und dann wird die Anzeige erzeugt:
1
void show_something_on_the_screen(){
2
3
  while(get_running()){
4
5
     show_new_text();
6
     delay(time);
7
 
8
  }
9
}

Meine Frage: Ist es sinnvoll den Wert von running in der while-Schleife 
ständig per Methode get_running() auszulesen? Oder ist es doch besser 
direkt auf die Variable zuzugreifen? Also while(running) bla bla bla.


Danke!

von Alexander F. (gustin)


Lesenswert?

Die getter/setter sind zum einen dazu da falsche Zuweisungen
auszuschließen.
Klassisches Besipiel: bei einer Klasse für eine Bruchzahl
wird 0 für den Nenner zugewiesen.
Wenn du direkten Zugriff auf die Variable hast, kannst du
die 0 zuweisen und das Programm schmiert eventuell ab.
Über eine set-Methode kannst du vorher prüfen, ob die
übergebene Zahl !=0 ist.

Bei einem Bool dürfte das egal sein, musst nur drauf achten,
dass du eine initiale Zuweisung im (Standard-)Konstruktor
hast, weil dein Bool sonst mit NULL initialisiert wird,
was weder true noch false ist.

Zum anderen kannst du aber im setter auch eine Änderungsmethode
abhandeln und damit deinem anderen Programmteil mitteilen,
dass sich deine Variable geändert hat, ohne pausenlos
den Zustand prüfen zu lassen.
Damit könntest du dir die while-Schleife eventuell sparen.

von Kaj (Gast)


Lesenswert?

Alexander F. schrieb:
> musst nur drauf achten,
> dass du eine initiale Zuweisung im (Standard-)Konstruktor
> hast, weil dein Bool sonst mit NULL initialisiert wird,
In der Annahme das der Codeschnippsel C++ ist:

1. Ein Bool kann per Definition nur die Werte true und false annehmen 
kann. Er wird aber ganz sicher nicht mit NULL initialisiert.

2. Wenn eine Variable nicht initialisiert wird, hat sie einen 
Zufallswert, naemlich den Wert der da gerade im Speicher steht, und 
dieser Wert wird dann entweder als true oder als false interpretiert. 
Sie wird nicht nur nicht mit NULL initialisiert, sie wird gar nicht 
initialisiert.

3. In anderen Sprachen, wie z.B. Python gibt es neben True und False 
noch das Nichts, None. Und None ist nochmal was anderes als NULL.

Alexander F. schrieb:
> weil dein Bool sonst mit NULL initialisiert wird,
> was weder true noch false ist.
In C++ gibt es nicht anderes als true und false fuer bool. Werte koennen 
aber als true oder false interpretiert werden. Dabei gilt: Ein Wert = 0 
wird als false, alle Werte != 0 als true interpretiert. NULL kann es an 
der Stelle also nicht geben. Wenn du einem bool den Wert NULL zuweist, 
wird dieser Wert vermutlich als false interpretiert werden.

von zitter_ned_aso (Gast)


Lesenswert?

Alexander F. schrieb:
> Zum anderen kannst du aber im setter auch eine Änderungsmethode
> abhandeln und damit deinem anderen Programmteil mitteilen,
> dass sich deine Variable geändert hat

Ja, das hört sich besser an als ständig eine Prüffunktion aufzurufen.

Also prüfen in der "set"-Methode den Wert.

Und bei

running==false

gleich den Thread pausieren.

Und bei

running==true

den Thread fortsetzen.

von Alexander F. (gustin)


Lesenswert?

Da hast du recht Kaj, war da wohl auf dem falschen Dampfer.
Bin momentan viel mit C# unterwegs, da wird sonst ales zu
null initialisiert, außer ein paar Primitive Datentypen wie
bool, int, float etc. dachte das gilt dort für alle Datentypen.

von Mark B. (markbrandis)


Lesenswert?

zitter_ned_aso schrieb:
> Den Verlauf steuert die (private) Klassenvariable "bool running".  Man
> sagt ja dass auf die Klassenvariablen per "set"/"get"-Methoden
> zugegriffen werden soll.

Manche wiederum sagen, dass genau das eher ein Zeichen von schlechtem 
Software-Design ist. Siehe z.B.:

https://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html

: Bearbeitet durch User
von Tom (Gast)


Lesenswert?

zitter_ned_aso schrieb:
> Man
> sagt ja dass auf die Klassenvariablen per "set"/"get"-Methoden
> zugegriffen werden soll.

Man soll überhaupt nicht von außen in den Membervariablen herum 
pfuschen.
Man kann aber einem Objekt irgendwas befehlen ( void start(); void 
stop(); ) oder einen Status abfragen ( bool is_running(); ). Ob dahinter 
irgendwelche Membervariablen abgefragt oder gesetzt werden, ist ein 
Implementierungsdetail, das außerhalb der Klasse keinen etwas angeht.

Für jeden Member hingeklatschte Getter und Setter sind normalerweise 
überflüssig. Wenn sie nicht überflüssig sind und von außen reger 
Gebrauch davon gemacht wird, ist das ein Zeichen für unsauberes Design.

von Rolf M. (rmagnus)


Lesenswert?

Kaj schrieb:
> Alexander F. schrieb:
>> weil dein Bool sonst mit NULL initialisiert wird,
>> was weder true noch false ist.
> In C++ gibt es nicht anderes als true und false fuer bool. Werte koennen
> aber als true oder false interpretiert werden. Dabei gilt: Ein Wert = 0
> wird als false, alle Werte != 0 als true interpretiert.

Das stimmt nicht ganz. Wenn du einen Integer nach bool konvertierst, 
dann ist das von dir genannte die Regel, wie diese Konvertierung 
stattfindet.
Darum geht's hier aber nicht, sondern um einen uninitialisierten bool, 
in dem irgendwas drin stehen kann. Und je nachdem, wie bool auf dem 
jeweiligen Compiler implementiert ist, kann sich da auch ein eigentlich 
ungültiger Wert ergeben, der weder true noch false ist.
NULL ist natürlich Quatsch, denn das existiert nur im Zeigerkontext.

von Kaj (Gast)


Lesenswert?

Rolf M. schrieb:
> Und je nachdem, wie bool auf dem
> jeweiligen Compiler implementiert ist, kann sich da auch ein eigentlich
> ungültiger Wert ergeben, der weder true noch false ist.
Das ist richtig. Aber der Wert wird als true oder false interpretiert. 
Das heisst aber nicht, das der Konkrete Wert true oder false ist. Und 
genau dieser Wortlaut macht den Unterschied.
Kaj schrieb:
> Werte koennen
> aber als true oder false interpretiert werden. Dabei gilt: Ein Wert = 0
> wird als false, alle Werte != 0 als true interpretiert.
Es gibt nur 2 Moeglihckeiten: Der Wert ist 0 oder eben nicht. Und dann 
kann man den Wert auch interpretieren. Natuerlich kann ich einen bool 
mit NULL initialisieren, macht nur halt nicht soviel Sinn.

Waere mir zumindestens nicht bekannt, das wenn du den Wert eines 
uninitialisierten bools abfragt dann weder true noch false rauskommt.
1
#include <iostream>
2
3
using namespace std;
4
5
6
int main(void)
7
{
8
  bool x;
9
10
  if (x) {
11
    cout << "true" << endl;
12
  } else if (!x) {
13
    cout << "false" << endl;
14
  } else {
15
    cout << "what ever" << endl;
16
  }
17
18
  return 0;
19
}

Spielt aber keine Rolle, da das undefined Behavior ist. Also ja, es 
koennte alles raus kommen. Auch der Mann im Mond. :)

von Rolf M. (rmagnus)


Lesenswert?

Kaj schrieb:
> Rolf M. schrieb:
>> Und je nachdem, wie bool auf dem
>> jeweiligen Compiler implementiert ist, kann sich da auch ein eigentlich
>> ungültiger Wert ergeben, der weder true noch false ist.
> Das ist richtig. Aber der Wert wird als true oder false interpretiert.
> Das heisst aber nicht, das der Konkrete Wert true oder false ist. Und
> genau dieser Wortlaut macht den Unterschied.

Aber es bleibt komplett dem Compiler überlassen, welche Bitpatterns für 
true und welche für false verwendet werden - oder was passiert, wenn man 
einen bool hat, in dem keines dieser Bitpatterns steht, weil er nicht 
auf dem offiziellen Weg mit einem Wert belegt wurde. Kann auch sein, 
dass er an einer Stelle als true, an einer anderen als false 
interpretiert wird.

> Es gibt nur 2 Moeglihckeiten: Der Wert ist 0 oder eben nicht.

Da er mehr als 1 Bit hat, gibt's mehr als 2 Möglichkeiten. Der Compiler 
kann auch definieren, dass das Bitpattern 00000000 als false gilt und 
11111111 als true und alles andere nicht weiter bedacht wird, da es in 
einem gültigen Programm nicht vorkommt.

> Spielt aber keine Rolle, da das undefined Behavior ist. Also ja, es
> koennte alles raus kommen. Auch der Mann im Mond. :)

Ja genau. Darauf wollte ich hinaus.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Du greifst also von mehreren Threads auf die Boolean-Variable zu? Dann 
solltest du std::atomic_flag oder std::atomic<bool> benutzen, weil bei 
einem "bool" von C++ nicht garantiert ist, dass gleichzeitige Zugriffe 
konsistent sind. Ob es wirklich schief gehen kann hängt von der 
Plattform ab, aber man möchte ja korrekten portablen Code schreiben...

Von mehreren Threads auf eine GUI zuzugreifen geht meistens sowieso 
ziemlich schief.

von A. S. (Gast)


Lesenswert?

Rolf M. schrieb:
> Der Compiler kann auch definieren, dass das Bitpattern 00000000 als
> false gilt und 11111111 als true und alles andere nicht weiter bedacht
> wird, da es in einem gültigen Programm nicht vorkommt.

Welche Sprache? C? Dort ist der wert 0 als false und 1 als true 
festgelegt. Und alle anderen Werte werden als true interpretiert.

Probleme gibt es also, wenn man irgendwie mit true vergleicht (No Go!) 
Oder verschiedene bool-typen unterschiedlicher Bitbreiten hat und 
zuweist (eigentlich auch ein No-Go)

von Rolf M. (rmagnus)


Lesenswert?

A. S. schrieb:
> Rolf M. schrieb:
>> Der Compiler kann auch definieren, dass das Bitpattern 00000000 als
>> false gilt und 11111111 als true und alles andere nicht weiter bedacht
>> wird, da es in einem gültigen Programm nicht vorkommt.
>
> Welche Sprache? C?

Wir sprechen von C++, aber für C gilt das auch.

> Dort ist der wert 0 als false und 1 als true festgelegt. Und alle anderen
> Werte werden als true interpretiert.

Da muss ich mich wiederholen:

Rolf M. schrieb:
> Das stimmt nicht ganz. Wenn du einen Integer nach bool konvertierst,
> dann ist das von dir genannte die Regel, wie diese Konvertierung
> stattfindet.
> Darum geht's hier aber nicht, sondern um einen uninitialisierten bool,
> in dem irgendwas drin stehen kann.


> Probleme gibt es also, wenn man irgendwie mit true vergleicht (No Go!)

Sofern du nicht bool, sondern z.B. int verwendest.

> Oder verschiedene bool-typen unterschiedlicher Bitbreiten hat und
> zuweist (eigentlich auch ein No-Go)

Auch das gilt natürlich nur für irgendwelche selbst definierten Sachen, 
die eigentlich Integer sind.

von Mehmet K. (mkmk)


Lesenswert?

Auf Membervariablen nur durch Methoden zuzugreifen hat desweiteren auch 
den Vorteil, dass man im Fehlerfall sich mit dem Debugger nur an einer 
Stelle Gewehr-bei-Fuss aufstellen muss.

von Pandur S. (jetztnicht)


Lesenswert?

Der Unterschied beim Zugriff auf eine Variable als Zugriff auf die 
Variable selbst und als Funktion liegt darin, dass die Funktion weitere 
Aktionen enthalten kann. Im Lese- sowie im Schreibzugriff.

Die Variable kann zB auch in einem Ringbuffer liegen.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.