Ich möchte gerne die Werte für den geraden Wert als const
deklarieren, wenn möglich, und durch die Suche nach SO fand ich, dass das ist nicht zu ungewöhnlich . So:
Aber ich frage mich: const
für Werte ist ein Implementierungsdetail meiner Funktion, nicht Teil ihrer Schnittstelle. Es scheint unnötig, es in den Prototyp zu bringen.
Dieser Prototyp für die obige Funktion scheint gut zu funktionieren:
%Vor%Aber ich habe von Problemen gehört, die z.B. Die Erklärung der Hauptfunktion argc als const kann zu Problemen führen:
%Vor% Das heißt also, dass int add(int a, int b)
und int add(const int a, const int b)
doch nicht identisch sind?
Und wenn es technisch in Ordnung ist, sollte ich das tun? Ich könnte auch Variablennamen im Prototyp weglassen, aber ich tue es nicht, also sollte ich vielleicht auch nicht const
weglassen?
Es ist nicht in Ordnung, dass der Funktionstyp sich unterscheidet, aber Sie müssen wissen, was Teil des Funktionstyps ist und was nicht. In Ihrem Fall ist die const
für die Parameter nicht signifikant, daher ist der Funktionstyp derselbe, obwohl die -Deklaration so aussieht, als ob sie sich von der -Definition unterscheidet.
In deinem Fall ist es
8.3.5 Funktionen [dcl.fct]
5 Ein einzelner Name kann für mehrere verschiedene Funktionen in einem einzigen Bereich verwendet werden; das ist Funktionsüberlastung (Abschnitt 13). Alle Deklarationen für eine Funktion müssen sowohl im Rückgabetyp als auch in der Parametertypliste genau übereinstimmen. Der Typ einer Funktion wird anhand der folgenden Regeln bestimmt. Der Typ jedes Parameters (einschließlich der Funktionsparameter-Packs) wird aus seinem eigenen Deklarationsspezifikator-Seq und Deklarator bestimmt. Nach Bestimmen des Typs jedes Parameters, jeder Parameter vom Typ "Array von T" oder "Funktion, die T zurückgibt" wird eingestellt, um "Zeiger zu T" oder "Zeiger zu Funktion, die T zurückgibt", zu sein. Nach dem Erstellen der Liste der Parametertypen werden alle übergeordneten cv-Qualifiers, die einen Parametertyp modifizieren, beim Bilden des Funktionstyps gelöscht. Die resultierende Liste der transformierten Parametertypen und das Vorhandensein oder Fehlen der Ellipse oder eines Funktionsparameterpakets ist die Parametertypliste der Funktion. [Hinweis: Diese Umwandlung funktioniert nicht beeinflussen die Arten der Parameter. Zum Beispiel sind
int(*)(const int p, decltype(p)*)
undint(*)(int, const int*)
identische Typen. - Endnote]
Wie es scheint, braucht es eine Erklärung, also hier: Der wichtige Satz in unserem Fall ist: Nach dem Erstellen der Liste der Parametertypen werden alle cv-Qualifikationsmerkmale auf oberster Ebene, die einen Parametertyp modifizieren, gelöscht den Funktionstyp bilden.
Dies bedeutet, dass alle Top-Level cv-Qualifier entfernt werden. Um zu erklären, was Top-Level bedeutet, schreibe ich Typen auf eine illegale Weise, um zu betonen, worauf sich ein const
bezieht:
const int
= (const (int))
- & gt; Dies ist ein Top-Level const
const int*
= ((const (int))*)
- & gt; nicht auf oberster Ebene, sondern auf der zweiten Ebene const int* const
= (((const (int))*) const)
- & gt; der zweite const
ist auf oberster Ebene const int&
= ((const (int))&)
- & gt; nicht auf oberster Ebene Ich hoffe, dass dies einige Missverständnisse über Funktionstypen aufhebt.
Für Ihre anderen Fragen: Ich würde empfehlen, die Deklaration und die Definition identisch zu halten, da dies die Leute verwirren könnte (wie diese Frage belegt).
Für das Beispiel von main
, das Sie angegeben haben:
entspricht nach dem obigen Zitat aus dem Standard:
%Vor% Das hinzugefügte const
für argv
endet nicht als Top-Level const
, das entfernt wird. Es ist daher ein schlecht gestalteter Funktionstyp für main
, der Folgendes erwartet:
Sie haben die letzte Frage über das Auslassen der Parameternamen: Ich würde es nicht tun, weil sie für mich Teil der Dokumentation der Funktion sind. Sie kommunizieren die Absicht und die Semantik der Funktion (wenn Sie sie mit Bedacht wählen).
Es sollte in Ordnung sein, unterschiedliche Toplevel const
für Funktionsparameter zwischen Deklarationen und Definitionen der Funktion zu haben, aber beachten Sie, dass nicht alle Compiler fehlerfrei sind. Zum Beispiel hat der Oracle Sun-Compiler ein lange bestehendes Problem , in dem es% macht. co_de% und int f(int)
anders.
Um jede mögliche Verwirrung zu vermeiden, die Sie wirklich weitergeben wollten, empfehle ich normalerweise, die oberste Ebene int f(const int)
in öffentlichen Funktionsdeklarationen zu vermeiden und mögliche Compiler-Probleme zu vermeiden, die ich auch in Funktionsdefinitionen vermeiden würde / p>
(Beachten Sie, dass das Ändern von const
in const
in einer Argumentliste nicht die oberste Ebene const enthält, sondern eine echte Signaturänderung. char **
wäre nur äquivalent zu const char* const argv[]
in einer Funktionsparameterliste.)
const für Werte ist ein Implementierungsdetail meiner Funktion, nicht Teil ihrer Schnittstelle.
Das ist der Fehler in deinem Denken, wenn du über Referenzen und Zeiger sprichst const
hat alles mit der Schnittstelle zu tun, es teilt dem Programmierer mit, dass das, was du passierst, nicht von der Funktion verändert wird. Es teilt dem Compiler das gleiche mit und bindet den Programmierer an diesen Vertrag.
Eine Funktion mit einem const
Argument und einer mit einem nicht const
Argument ist anders.
Bei Wertübergabe werden jedoch die Argumente kopiert. In diesem Fall ist es kein Problem, sie zu ändern. Ihre int
s werden als Wert übergeben, wobei diese const
nicht verwendet wird viel Unterschied.
Ich persönlich glaube jedoch nicht, dass dies ein Grund ist, inkonsistente Schnittstellen zu missbrauchen und Schnittstellen an einem Ort anders zu machen.
In der Erwägung, dass ref nach const
ganz anders ist als ref zu non const
.
Tags und Links c const c++ header function-prototypes