In dem Fall veränderst du den Zustand des Objekts. Dann ist eine "normale" Referenz angebracht. Wenn man Methoden die Objekte nicht verändern auch noch const deklariert wird das deutlicher
Hallo,
okay, dann hier ohne const. Nur so richtig logisch ist das Verhalten für mich nicht. Das Objekt was übergeben wird bleibt ja konstant, ich tausche das nicht aus. Und was die Methode macht sollte doch egal sein, ich übergebe ja das Objekt und nicht die Methode.
Nur so richtig logisch ist das Verhalten für mich nicht.
Wenn du einen Zeiger übergibst:
template <class L>
void blinke (const L *led, unsigned long interval)
wird der Zeiger so als konstant definiert.
Darf sich also nicht ändern.
Die Daten innerhalb des Objektes dürfen sich sehr wohl ändern.
Wenn du eine Referenz übergibst
template <class L>
void blinke (const L &led, unsigned long interval)
Wird das Objekt als konstant definiert
Seine Eigenschaften dürfen dann nicht geändert werden.
Die Definition, als konstant, erlaubt dem Compiler weitergehende Optimierungen und verschafft ihm die Möglichkeit, erbost aufzuschreien, wenn der Programmierer gegen seine eigenen Regeln verstößt.
Die betreffende Methode müsste/sollte dann auch als konstant definiert werden...
z.B. so:
void Output::set(const bool state) const
{
if (state) setHigh();
else setLow();
}
Ob das in diesem Fall möglich/erlaubt ist, kann ich dir nicht sagen, denn schließlich werden ja Veränderungen vorgenommen.
Hallo,
aha, die kleinen aber feinen Unterschiede. Verstanden.
Das mit const in der Methode habe ich probiert, gleiche Warnung wie vorher.
Dann will ich den Compiler nicht weiter nerven.
Danke euch.
Hallo,
nochmal ich, hatte jetzt "konstante" Methoden in der Mache, ohne Parameter.
Auch hier meckert der Compiler wenn ich ein Objekt als konstante Referenz übergebe.
Kann es sein das konstante Referenzen mit Objekten nicht funktioniert?
Kann es sein das ihm nicht die Methoden stören sondern die verfügbaren Klassen für die Objekte?
Ich meine ich könnte das Objekt Led_77 statt mit Output auch mit Input oder InputPullup initialisieren.
Input Led_77 (MCP_I2C_ADR, 9)
InputPullup Led_77 (MCP_I2C_ADR, 9)
Output Led_77 (MCP_I2C_ADR, 9)
Wenn das hier zu weit führt sagt Bescheid.
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino: In instantiation of 'void init_Ref(const T&) [with T = InputPullup]':
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:80:21: required from here
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:31:3: warning: passing 'const InputPullup' as 'this' argument discards qualifiers [-fpermissive]
pT.init();
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:13:0:
.../docMCP23017.h:66:8: note: in call to 'void InputPullup::init()'
void init (void);
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino: In instantiation of 'void init_Ref(const T&) [with T = Output]':
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:84:18: required from here
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:31:3: warning: passing 'const Output' as 'this' argument discards qualifiers [-fpermissive]
pT.init();
...\docMCP23017_Lib_Entwicklungstestcode_Steuerung_002.ino:13:0:
...\docMCP23017/docMCP23017.h:28:8: note: in call to 'void Output::init()'
void init (void);
template <class L>
void init (const L &pL)
{
pL.init();
}
Aufruf:
init(Led_77);
Methode:
void Output::init()
{
uint8_t is = 0;
readOneRegister (get_DIR_Port(pin), is); // IODIR Port lesen
is &= ~(getBitMaske(pin)); // Bit löschen
writeOneRegister (get_DIR_Port(pin), is); // modifizierte Maske zurückschreiben
}
Grundsätzlich geht das schon....
Hier mal eine funktionierende konstante Stilblüte:
class Inner
{
public:
int tuwas(const int value) const
{
return value * 2;
}
};
class Outer
{
public:
void tuwas(const Inner &inner,const int value) const
{
Serial.println(inner.tuwas(value));
}
};
const Inner inner;
const Outer outer;
void setup()
{
Serial.begin(9600);
Serial.println("Start");
outer.tuwas(inner,3);
}
void loop()
{
}
Hallo,
mit grundsätzlich bzw. mit normaler Variablen/Wertübergabe habe ich auch kein Problem ...
Ich merke mir erstmal mit Objekten kein const.
Ich versuche es mal von der anderen Seite her. Wenn Methoden als const deklariert werden, dann dürfen sie auch auf const-Objekten aufgerufen werden. Dabei ist es unerheblich, ob die Methoden etwas ändern.
Die Klassen:
class MyClass1 {
public:
int getVal() {
return val * 2;
}
private:
int val = 5;
};
class MyClass2 {
public:
int getVal() const {
return val * 2;
}
private:
int val = 10;
};
Die Test-Ino:
#include "MyClass.h"
MyClass1 mc1; // normales Objekt
const MyClass1 mc1c; // konstantes Objekt
MyClass2 mc2; // // normales Objekt
const MyClass2 mc2c; // konstantes Objekt
void setup() {
Serial.begin(115200);
Serial.println(mc1.getVal());
Serial.println(mc1c.getVal()); // <---- Warnung
Serial.println(mc2.getVal());
Serial.println(mc2c.getVal()); // <----- keine Warnung, da die Methode als const gekennzeichnet ist
}
void loop() {}
Warnung:
F:\arduino-1.8.5_mit_2.4.2\portable\sketchbook\const_Klasse\const_Klasse.ino:12:30: warning: passing 'const MyClass1' as 'this' argument of 'int MyClass1::getVal()' discards qualifiers [-fpermissive]
Serial.println(mc1c.getVal());
Gruß Tommy
Hi
Verstehe ich nicht - die Deklaration von mc1c und mc2c ist doch identisch, wo ist bei mc2c da 'mehr' const, als bei mc1c?
MfG
Du solltest Dir auch die Klassen anschauen und alles lesen.
Gruß Tommy
Hi
Aaaahhh ... sorry, hatte nicht gesehen, daß MyClass1 und MyClass2 schon verschieden sind - hatte bei Beiden die 1 gesehen.
Ok, so wird ein Schuh daraus, ich sehe Unterschiede und kann mit Zusammenreimen anfangen!
Danke für's mit der Nase drauf stupsen
MfG
Hallo,
schönes Bsp. Tommy. Danke.
Kann ich derzeit bei mir leider nicht umsetzen. Weil das einen übelsten Rattenschwanz in meiner Lib nach sich zieht. Selbst Hilfsfunktionen werden in meiner .cpp dann wegen const angemeckert. Das geht vom Hunderten ins Tausende. Das muss ich nochmal im Kleinen nachvollziehen, also meine Lib abspecken.
Was mir dabei gleichzeitig durch die Birne schießt ist, warum ein Objekt überhaupt const also read only machen?
Einmal initialisiert ist es doch unveränderbar. Eine Objekt Übergabe per Referenz ohne const kann doch nicht schief gehen.
Zudem die Lesbarkeit durch Tausende const extrem leidet.
Übersehe ich etwas?
Was mir dabei gleichzeitig durch die Birne schießt ist, warum ein Objekt überhaupt const also read only machen?
Einmal initialisiert ist es doch unveränderbar. Eine Objekt Übergabe per Referenz ohne const kann doch nicht schief gehen.
const verhindert versehentliche Veränderungen.
Grundregel:
Je expliziter/restriktiver man die Dinge ausformuliert, desto weniger Fehler/Dummheiten kann man damit anstellen.
Und, wie schon gesagt... dem Optimierer hilfts auch noch etwas auf die Sprünge.
tommy:
Dabei ist es unerheblich, ob die Methoden etwas ändern.
? Verstehe ich jetzt nicht.
Das wird doch gerade verhindert durch const.
versuche mal
class MyClass2 {
public:
int getVal() const {
val *= 2; // das sollte nicht möglich sein
return val;
}
private:
int val = 10;
};
Das Original - getVal() ändert nichts am this - Objekt, sollte daher als const deklariert werden. Dann kann man auch Instanzen dieser Klasse als const deklarieren, ohne dass man sich die Warnung "discards qualifiers" einfängt.
Aber du hast recht, @Doc, wenn man einmal anfängt, ordentlich alles mit const zu deklarieren, zieht das gern einen elenden Rattenschwanz nach sich, besonders und solange in verwendeten Funktionen nicht alles const ist, was const sein sollte.
Es gab mal ein Arduino, da waren nochnichtmal PROGMEM-Zugriffe const, wenn ich mich recht erinnere.
Und bei Zeigern muss man gut zwischen einem const Zeiger und einem Zeiger auf const unterscheiden.
Das Ganze kann man gern mit "Schwer lesbar" verwechseln.
michael_x:
? Verstehe ich jetzt nicht.
Das wird doch gerade verhindert durch const.
Ich wollte damit nur ausdrücken, dass die Warnung auch kommt, wenn die Methode nichts in der Klasse ändert. Das war wahrscheinlich unglücklich formuliert.
Wenn Du tatsächlich was änderst, kommt ein Error. Es sei denn, Du hast die Variable als mutable gekennzeichnet, dann kannst Du sie auch in einem const-Objekt ändern.
Gruß Tommy
Hallo,
gut das wir darüber gesprochen haben.
Danke euch allen.