designfrage const correctness, error code
-
hallo leute
dummer titel, aber faellt mir grad nix ein.
folgendes beispiel (nur pseudo code):
class Punkte { public: auto index(int i) { error_code = 0; if(i >= container.size()) { error_code = 1; return 0; } return container[i]; } private: int error_code; std::vector<int> container; };die function 'index' sollte eigendlich const sein, weil nur lesen drauf zugegriffen wird. durch den error_code geht das aber nicht.
sollte man nun index const machen und error_code mutable oder die function nicht-const lassen ?
Meep Meep
-
Huhu
Ich würde das mit dem error_code nicht so machen (sehe ich akt. kein Grund zu).
Der error_code ist doch Methodenabhängig, daher würde ich es eher so lösen:
auto index(unsigned int i, bool* ok = nullptr) const { if(i >= size()) { if(ok) { *ok = false; } return 0; } // ... }Oder mit den Exceptions arbeiten ... die mit std::vector<>::at() eh geworfen wird.
Dann kannst Du auch die Methode mit const markieren.Grüße
-
das object wird in einer DLL datei erstellt. also geht das mit exceptions nicht.
den error_code hab ich im object drinnen. der ist nicht nur ein int, sondern eine recht aufwendige klasse. deshaölb hab ich auch geschrieben das es pseudocode ist.mir ist gerade eingefallen das man es mit einem const_cast auch loesen koennte ?
waere das in dem pseudobeispiel angebracht ?
-
Wenn der error_code nur intern in deiner Klasse benutzt wird und keine Außenwirkung hat, kannst Du error_code als mutable deklarieren, dann kann man diese auch in einer const-Methode ändern.
mutable int error_code;
-
Meep Meep schrieb:
das object wird in einer DLL datei erstellt. also geht das mit exceptions nicht.
Wie kommst du darauf?
Ansonsten bietet sich ein tuple<bool,int> an.
-
wo waere da jetzt der unterschied zwischen mutable und const_cast ?
die error klasse ist nicht-constant. gesetzt wird sie nur ueber die klasse selber. kann aber jeder zeit von aussen her ueberprueft werden.
eigendlich habe ich nur 2 member functions die const sind und den zustand von error aendern wuerden.Meep Meep
-
manni66 schrieb:
Meep Meep schrieb:
das object wird in einer DLL datei erstellt. also geht das mit exceptions nicht.
Wie kommst du darauf?
Ansonsten bietet sich ein tuple<bool,int> an.
Wir kommst du darauf?
exceptions ueber DLL grenzen funktioniert nur unter bestimmten voraussetzungen, die bei mir noch gegeben sind.
und nein, ich will nicht einen errorcode in form eines integers oder aehnlich an den aufrufer uebergeben.
die error-klasse wird auch intensiv intern genutzt. nach aussen hin kann nur lesend darauf zugegriffen werden um z.b. den status der letzten operation zu ueberpruefen.
-
Meep Meep schrieb:
wo waere da jetzt der unterschied zwischen mutable und const_cast ?
mutablemacht als Member-Eigenschaft unmissverständlich deutlich, dass der Member eine Sonderstellung einnimmt und beabsichtigt ist, dass die Variable nichts mit der "logischen" const-ness des Objekts zu tun hat (Code-Verständlichkeit).
const_castwirkt auf mich immer wie ein schmutziger Hack, besonders wenn der cast irgendwo im tief Code versteckt ist.Falls sich der error-Member wirklich nicht vermeiden lässt, dann mach in am besten
mutableund synchronisiere ihn zusätzlich noch z.B. mit einem Mutex (auchmutable, Mutex-Member sind die geborenen Mutanten ;)).
Als Nutzer einer Klasse gehöre ich nämlich zu den Leuten die erwarten dass mein Code keine Data Races enthält, wenn nurconst-qualifizerte Member-Funktionen aufgerufen werden
Finnegan
-
wie meinst du das mit den Data Races ?
-
Meep Meep schrieb:
wie meinst du das mit den Data Races ?
2 Threads rufen konkurrierend die unverfänglich
const-qualifizierteindex()-Funktion für das selbe Objekt mit einem zu grosseniauf ->error_codewird ohne Synchronisation (atomic/mutex) von zwei Threads geschrieben -> data race -> undefined behavior.
-
o, damit hab ich dann kein problem, weil auf die objecte nur serialisiert zugegriffen werden kann. pro thread kann nur max. ein object einer klasse existieren. aber danke trotzdem fuer den hinweis. haette daran nicht gedacht.
Meep Meep
-
Meep Meep schrieb:
o, damit hab ich dann kein problem, weil auf die objecte nur serialisiert zugegriffen werden kann. pro thread kann nur max. ein object einer klasse existieren. aber danke trotzdem fuer den hinweis. haette daran nicht gedacht.
Wenn eine Klasse in einer streng kontrollierten Umgebung verwendet wird kann man das zwar so machen, ich persönlich mache mir allerdings fast immer
die Mühe den Code so zu schreiben, dass er nicht nur unter bestimmten Bedingungen korrekt ist.Besonders bei längerlebigen Projekten tendiert Code nämlich oft dazu im Laufe der Zeit in einem ganz anderen Kontext zu laufen als ursprünglich beabsichtigt.
Nach meinem Bauchgefühl ist das so etwas wie ein blankesnew/delete-Paar - das kann man zwar durchaus korrekt einsetzen, wenn einem z.B. dazwischen keine
Exceptions um die Ohren fliegen, aber jede zusätzliche Regel die man später beachten muss, wenn man den Code wieder anfasst macht ein größeres Projekt
instabiler gegenüber Änderungen und somit schwerer zu bändigen. Wenn man sowas auf die Spitze treibt hat man nachher eines von diesen berüchtigten
Programmen bei dem fast jeder Bugfix oder ein neues Feature einen neuen "WTF!?"-Bug an einer gan anderen Stelle aufreisst
Finnegan