Ich hab ein kleines Problem beim Programmieren der Steuerung eines Beleuchtungssystems. Im Programm habe ich verschiedene Klassen angelegt (verschiedene Lampenprofile). Beim Aufruf einer Prozedur der Klasse möchte ich nur die Ausführungszeit übergeben. In der Prozedur müsste dann eine Variable ausgelesen werden, die global angelegt ist (int Uhrzeit-->setzt sich aus Stunde und Minute zusammen). Leider ist diese nicht in der Klasse gültig.
Muss ich Uhrzeit wirklich über call-by übergeben, oder gibt es eine elegantere Lösung?
Man kann Variablen auch als "extern" deklarieren.
Das hilft dem Linker auf die Sprünge.
Wenn die globale Variable ausschließlich oder überwiegend von deiner Klasse benutzt wird,
könntest du sie auch als static Element deiner Klasse definieren.
Die Sichtbarkeit kannst du dann gut steuern und auch ausserhalb der Memberfunktionen wird die Zusammengehörigkeit deutlich.
Man kann Variablen auch als "extern" deklarieren.
Das hilft dem Linker auf die Sprünge.
-->Wie genau funktioniert extern ? Soweit ich verstanden habe deklariert es eine Variable ohne einen Wert zuzuweisen....
Wenn ich jedenfalls extern int Uhrzeit; in die Klasse einfüge, meckert er folgendes: "storage class specified for 'Uhrzeit'"
Wenn die globale Variable ausschließlich oder überwiegend von deiner Klasse benutzt wird,
könntest du sie auch als static Element deiner Klasse definieren.
-->Das funktioniert leider nicht, die Variable Uhrzeit wird in einer Methode in der loop() stets verändert.
Mit Uhrzeit möchte ich übrigens nicht die normale Uhrzeit speichern, sondern eine Uhrzeit für eine Modellbahnanlage simulieren.
Du schreibst in irgendeiner Datei die Definition:
int Uhrzeit = 4711;
Und in der Datei, wo du die globale Variable nutzen willst, die Deklaration:
extern int Uhrzeit;
Geschickter weise verteilt man das auf *.cpp und *.h Dateien.
Muss aber nicht....
DerLehmi:
-->Das funktioniert leider nicht, die Variable Uhrzeit wird in einer Methode in der loop() stets verändert.
Da sehe ich kein Problem.
class Beispiel
{
public:
static unsigned long Uhrzeit;
};
unsigned long Beispiel::Uhrzeit = 123456;
void loop() {
Beispiel::Uhrzeit = micros(); // damit sich das auch 'stets' ändert
}
*nachdenk...
Warum soll aus einer "Klasse" heraus überhaupt auf globale Variablen zugegriffen werden?
So weit ich das System von OOP im Allgemeinen - und Klassen im Speziellen - verstehe, kapselt eine Klasse doch alles rund um eine Aktion in sich, ohne zunächst mit globale Dinge interagieren zu müssen oder zu sollen. Wenn nun auf Variablen von "außen" zugegriffen werden soll, können diese doch eigentlich nur mittels "public" einem Objekt übergeben werden. Beim Auslesen müssten die innerhalb des Objektes ermittelten Ergebnisse ebenfalls nur wieder mittels einer "public" öffentlich zur Verfügung gestellt werden?! Ebenso verhält es sich doch m.E. mit Funktionen. Ein Programm außerhalb eines Objektes darf doch auch niemals in Konflikt mit den internen Verarbeitungen eines Objektes geraten (oder damit interagieren), wodurch es nicht mehr wirklich portierbar wäre?!
Dementsprechend wäre (nach meinem Verständnis) ein Konzept, welches aus einer Klasse heraus auf öffentliche Dinge zugreifen soll, eigentlich komplett gegen das eigentliche Prinzip von OOP - und sollte völlig neu überdacht und entwickelt werden!?
Wo ist hier evtl. mein Denkfehler?
Du meinst dass man nicht so einfach von außen auf Variablen innerhalb von Klassen zugreifen soll. Also anders herum. Das ist was anderes.
Aus einer Klasse heraus darf man auch auf globale Variablen zugreifen. Ob es eine gute Idee ist eine andere Frage, da man auch hier die Arbeit des Objekts einfach beeinflussen kann .
Was hier auch verwirrt ist die die Terminologie:
Beim Aufruf einer Prozedur der Klasse möchte ich nur die Ausführungszeit übergeben.
Eine Prozedur ist eine Funktion/Methode. Wobei es in machen Sprachen eine Funktion ohne Rückgabewert ist. C/C++ macht diesen Unterschied nicht.
Die Instanz einer Klasse ist ein Objekt.
Das hört sich eher so an als sollen Werte in einem Konstruktor übergeben werden. Dann können diese Variablen privat sein und nur innerhalb der Klasse verwendet werden.
Aus einer Klasse heraus darf man auch auf globale Variablen zugreifen. Ob es eine gute Idee ist eine andere Frage, da man auch hier die Arbeit des Objekts einfach beeinflussen kann .
Ja, das ist genau was ich meine. Ich würde gerne noch einen Schritt weiter gehen und sagen: "Das ist ein Fehler". Denn: Wenn ich einmal ein tolles Objekt bestens funtionierend entwickelt habe - falle ich beim nächsten Einsatz, wo die betreffenden "Globals" NICHT deklariert sind - sofort wieder auf die Nase. Und dann wäre meine (Spitzen-) Klasse mehr oder weniger nutz- und wertlos.
Das was du meinst, nennt sich "Dependency Injection".
Auf größeren Systemen macht es wirklich Sinn dieses Design Pattern vollständig umzusetzen.
Auf den winzigen AVRs eher nicht.
Zu Kompromissen, man wird gezwungen...
Es reicht ja schon wenn man die entsprechenden Variablen per Konstruktor an das Objekt übergibt. Und schon hat es seine eigenen Kopien davon. Wegen den paar Byte sollte man nicht kleinlich sein. Anders als im Eingangpost bemängelt ist das nämlich nicht unelegant.
Man kann dann immer noch Setter Methoden schreiben um diese Variablen später zu ändern wenn man das braucht.
Danke an dieser Stelle für Eure Antworten.
aktueller Stand: "extern int Uhrzeit" in die Prozedur des Objektes reingeschrieben, funktioniert soweit.
Die momentane Lösung unterscheidet sich von der Möglichkeit mit static nur im Ort der Deklarierung, oder? Wenn ich jetzt aber mehrere Klassen habe, die auf diese Variable zugreifen sollen, dann müsste ich (wenn ich in einer Klasse die Variable mit static erstelle), diese auch mittels extern in die anderen Klassen einbinden, oder?
Wenn ich einmal ein tolles Objekt bestens funtionierend entwickelt habe - falle ich beim nächsten Einsatz, wo die betreffenden "Globals" NICHT deklariert sind - sofort wieder auf die Nase.
-->Muss also entsprechend kommentiert werden....
Es reicht ja schon wenn man die entsprechenden Variablen per Konstruktor an das Objekt übergibt.
-->Das möchte ich eben vermeiden, weil es ziemlich unelegant aussieht, wenn man relativ viele Objekte anlegt. Ziel ist es, die Objekte einfach anzulegen, wobei nur der Pin übergeben wird, und die Nutzung dann nur mittels der Objekt-Prozeduren, wobei nur die Stellzeit übergeben werden soll.
Das Programm ist für Jemand, der sich mit Arduino noch nicht sonderlich auskennt. Von daher sollte die Konfiguration möglichst simpel und übersichtlich sein.
Sobald das Programm fertig ist werde ich es natürlich in einem extra-Post vorstellen, bin auf Meinungen gespannt^^ (und vielleicht gibt es den ein oder anderen Interessierten)
Dann hast du irgendwie den Sinn von Objekten nicht ganz verstanden. Es geht ja gerade darum das jedes Objekt seine eigenen Variablen hat, diese selbst verwaltet und alles gekapselt ist.
Man übergibt die Variablen/Daten beim Erstellen im Konstruktor. Was ist darin nicht einfach? Es ist sicherlich besser verständlich als sich irgendwie auf globale Variablen zu verlassen die wer weiß wo stehen