2009-04-01 5 views
5

Ich hatte den folgenden C++ - Code, wobei das Argument für meinen Konstruktor in der Deklaration eine andere Konstanz als die Definition des Konstruktors hatte.Nichtübereinstimmung zwischen Konstruktordefinition und Deklaration

Ich konnte dies ohne Warnungen mit g ++ kompilieren, sollte dieser Code kompilieren oder zumindest einige Warnungen geben? Es stellt sich heraus, dass der eingebaute C++ - Compiler auf 64-Bit-Solaris mir einen Linker-Fehler gegeben hat, so wie ich festgestellt habe, dass ein Problem aufgetreten ist.

Was ist die Regel für passende Argumente in diesem Fall? Liegt es an Compilern?

Antwort

7

In solchen Fällen darf der const-Bezeichner ommitt sein Ed von der Erklärung, weil es nichts für den Anrufer ändert.

Es spielt nur im Kontext der Implementierungsdetails eine Rolle. Deshalb ist es auf der Definition, aber nicht die Deklaration.

Beispiel:

//Both f and g have the same signature 
void f(int x); 
void g(const int x); 

void f(const int x)//this is allowed 
{ 
} 

void g(const int x) 
{ 
} 

Jeder f Aufruf sich nicht darum kümmern, dass Sie es als const zu behandeln gehen, weil es Ihre eigene Kopie der Variable ist.

Mit int * const x ist es das gleiche, es ist Ihre Kopie des Zeigers. Ob Sie auf etwas anderes zeigen können, spielt für den Anrufer keine Rolle.

Wenn Sie die erste Konstante in const int * const weggelassen haben, dann würde das einen Unterschied machen, weil es für den Aufrufer wichtig ist, wenn Sie die Daten ändern, auf die es zeigt.

Referenz: Die C++ Standard-, 8.3.5 Abs 3:

„Jede cv-Qualifier einen Parametertyp modifiziert wird gelöscht ... Solche cv-Qualifikations wirken sich nur auf die Definition des Parameters mit dem Körper der Funktion, sie haben keinen Einfluss auf den Funktionstyp“

+0

Bitte geben Sie Bezug auf den Standard. –

+0

Ich habe darüber geschrieben, wenn Sie weitere Beispiele benötigen: http://StackOverflow.com/Questions/269882/c-const-Question/274888#274888 –

+0

@ onebyone.livejournal.com: Danke. –

4

Betrachten Sie es als die gleiche Differenz zwischen

//testClass.hpp 
class testClass { 
    public: 
    testClass(const int x); 
}; 

//testClass.cpp 
testClass::testClass(int x) {} 

Welche auch kompiliert. Sie können nicht überladen, basierend auf der Konstanten eines Pass-by-Value-Parameters. Stellen Sie sich vor, diesen Fall:

void f(int x) { } 
void f(const int x) { } // Can't compile both of these. 

int main() 
{ 
    f(7); // Which gets called? 
} 

Aus dem Standard:

Parameterdeklarationen, die nur in der Gegenwart oder Abwesenheit von const und/oder flüchtig sind gleichwertig unterscheiden. Das heißt, die Konstanten und flüchtigen Typ-Spezifizierer für jeden Parameter Typ werden ignoriert, wenn festgelegt wird, welche Funktion deklariert, definiert oder aufgerufen wird. [Beispiel:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-End Beispiel] Nur die const und flüchtige Typ-Spezifizierer im äußersten Niveau des Parametertypen Spezifikation in dieser Mode ignoriert werden; const und flüchtige Typ-Spezifizierer vergrabene innerhalb eines Parameterart Spezifikation sind signifikant und kann verwendet werden distinguish überladene Funktion declarations.112) Insbesondere für jeden Typ T, „Zeiger auf T“ „Zeiger auf const T“und‚Zeiger auf flüchtigen T‘werden als eindeutige Parametertypen, ebenso wie‚Referenz auf T‘,‚T Referenz bis konst‘und ‚Bezug auf flüchtigen T.‘

0

Ist const int * const x nicht das gleiche wie const int * x weil du schon const?

+0

Nein. Im ersten Fall ist x ein Const-Zeiger auf eine Const-Ganzzahl. Im zweiten Fall ist x ein * nicht-const * -Zeiger auf eine const-ganze Zahl. –

+0

Insbesondere an erster Stelle können Sie weder x noch * x ändern. Im zweiten Fall können Sie x * nicht ändern, aber Sie können x ändern. Zum Beispiel könnte die zweite verwendet werden, um durch ein Array zu gehen (beispielsweise mit x ++), und das erste nicht. –

5

Dieses Beispiel explizit in der Überladungsauflösung Abschnitt bedeckt ist, 13,1/3B4:

Parameterdeklarationen, die nur in Gegenwart oder Abwesenheit von const unterscheiden und/oder flüchtig sind äquivalent. Das heißt, die Konstanten und flüchtigen Typspezifizierer für jeden Parametertyp werden ignoriert bei der Bestimmung, welche Funktion deklariert, definiert oder aufgerufen wird.

[Beispiel:

typedef const int cInt; 
int f (int); 
int f (const int); // redeclaration of f(int) 
int f (int) { ... } // definition of f(int) 
int f (cInt) { ... } // error: redefinition of f(int) 

-Ende Beispiel]

Also, es ist auf jeden Fall in Ordnung.

Verwandte Themen