Soweit ich hier und dort lese, sollte const
verwendet werden, wenn es möglich ist. Allerdings habe ich einen Fall, der mich immer stört.
Soll ich eine Elementfunktion als const
markieren, wenn sie keine Membervariablenwerte ändert, aber nicht konzeptionell eine const
-Funktion ist?
Zum Beispiel:
%Vor% Der Compiler akzeptiert die Konstante von start()
seit engine_
, da sich ein Zeiger nicht geändert hat. Es scheint jedoch so unrealistisch, zumindest IMO, dass eine Funktion namens start
in einer Klasse namens Car
ist const
eins!
Das Beispiel war nur ein kurzes Beispiel. In der Regel sollten einige interne Status der Klasse Car
entsprechend aktualisiert werden, sodass const
keyword nicht möglich ist. Das Mini-Beispiel sollte jedoch nur meine Idee veranschaulichen.
In Ihrem Fall erlaubt Ihnen der Compiler, start()
const wegen der unvollständigen Propagierung von constness durch Zeiger zu machen. Wenn Sie Ihren Zeiger durch das Objekt Engine
ersetzen, wird Ihre Frage verschwinden. Die Antwort lautet also nein, sie sollte in diesem Fall nicht const
sein, da Engine
als intelligenter Zeiger oder Instanz interne Details ist und die öffentliche Schnittstelle der Klasse Car
nicht beeinflussen sollte.
Soweit ich hier und da lese, sollte const nach Möglichkeit benutzt werden.
Diese Aussage ist viel zu generisch und sollte wie bei jedem generischen Vorschlag nicht in jedem Fall formell verwendet werden.
Eine einfache Metrik dafür, ob eine Funktion const
sein soll, ist dies:
Wenn comp1
und comp2
je unterschiedlich sein können, dann ist some_func
nicht const
.
Offensichtlich hat nicht jeder Typ operator==
overload, aber die meisten haben zumindest die konzeptionelle Idee, was Sie testen würden, um zu sehen, ob sie gleich sind. Verschiedene Car
Instanzen mit unterschiedlichen engine
Zuständen wären ungleich. Daher ist eine Funktion, die den engine
-Zustand ändert, nicht const
.
In Ihrem Beispiel möchten Sie vielleicht std :: experimental :: propagate_const :
%Vor% Dann kann Ihr start
nicht länger const
sein.
Die Bedeutung von const
kann variieren.
Etwas ist const
, wenn ==
beibehalten wird.
Etwas ist const
, wenn Ihr Typ der Referenzsemantik folgt und das, worauf Bezug genommen wird, nicht ändert.
Etwas ist const
, wenn es auf vernünftige Weise mit einem beliebigen rvalue oder lvalue verwendet werden kann.
Etwas ist const
, wenn es sicher ist, es aus mehreren Threads zu verwenden.
Etwas ist const
, wenn es als const
kompiliert wird.
Etwas ist const
, wenn der Zustand, den das Objekt behauptet, intern von ihm nicht mutiert wird.
All dies sind vernünftige Regeln, um zu entscheiden, ob eine Methode oder ein Argument const
ist.
Eine Sache, auf die man besonders achten sollte, ist, den Unterschied zwischen T const*
und T*const
zu kennen und nicht versehentlich die oberste Konstante als interne Konstante zu verwenden. Es ist nicht; t const iterator
es ist const_iterator
. Es ist nicht const gsl::span<int>
, es ist gsl::span<const int>
. Es ist nicht const unique_ptr<T>
, es ist unique_ptr<T const>
.
Andererseits ist vector
eine Wertesemantik typr; es gibt vor, dass sein Puffer ein Teil davon ist (obwohl dies eine Lüge ist). Es ist nicht vector<const T>
, es ist const vector<T>
.