2009-04-01 5 views
5

J'avais le code C++ suivant, où l'argument de mon constructeur dans la déclaration avait une constance différente de la définition du constructeur.Incompatibilité entre la définition du constructeur et la déclaration

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

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

j'ai pu compiler ce sans avertissement en utilisant g ++, si cela compilation de code ou au moins donner quelques avertissements? Il s'avère que le compilateur C++ intégré sur Solaris 64 bits m'a donné une erreur d'éditeur de liens, et c'est ainsi que j'ai remarqué qu'il y avait un problème.

Quelle est la règle sur la correspondance des arguments dans ce cas? Est-ce que c'est aux compilateurs?

Répondre

7

Dans ce cas, le spécificateur const est autorisé à être ommitt ed de la déclaration car cela ne change rien pour l'appelant.

Cela n'a d'importance que dans le contexte des détails d'implémentation. Voilà pourquoi c'est sur la définition mais pas la déclaration.

Exemple:

//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) 
{ 
} 

Toute personne appelant f ne se souciera pas que vous allez traiter comme const parce qu'il est votre propre copie de la variable.

Avec int * const x, c'est la même chose, c'est votre copie du pointeur. Si vous pouvez pointer vers quelque chose d'autre n'a pas d'importance pour l'appelant.

Si vous avez omis le premier const dans const int * const, cela ferait une différence car cela importait pour l'appelant si vous changiez les données vers lesquelles il pointe.

Référence: Le C++ standard, 8.3.5 par 3:

« Any-qualificatif de cv modifier un type de paramètre est supprimé ... Ces qualificatifs cv-affectent uniquement les définition du paramètre avec le corps de la fonction, ils ne affectent le type de fonction »

+0

Veuillez fournir une référence à la norme. –

+0

J'ai écrit à ce sujet ici, si vous avez besoin de plus d'exemples: http://stackoverflow.com/questions/269882/c-const-question/274888#274888 –

+0

@ onebyone.livejournal.com: Merci. –

4

le considérer comme la même différence entre

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

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

qui compile également. Vous ne pouvez pas surcharger en fonction de la constance d'un paramètre de valeur de transmission. Imaginez ce cas:

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

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

de la norme:

déclarations de paramètres qui diffèrent uniquement en présence ou l'absence de const et/ou volatiles sont équivalentes. En d'autres termes, les spécificateurs de type const et volatile pour chaque type de paramètre sont ignorés lors de la détermination de la fonction déclarée, définie ou appelée. [Exemple:

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) 

-fin exemple] Seul le const et -types spécificateurs volatils au niveau la plus externe du type de paramètre spécification sont ignorés dans ce mode ; const et de type-spécificateurs volatils enfouis à l'intérieur d'une spécification de type de paramètre sont importante et peuvent être utilisés pour distinguer les fonction surchargée declarations.112) En particulier, pour tout type T, « pointeur sur T, » « pointeur vers const T » et « pointeur vers volatile T » sont considérés comme types de paramètres distincts, comme sont « référence à T », « référence à const T, » et « référence à T. volatile »

0

est-const int * const x pas la même chose comme const int * x parce que vous avez déjà fait const?

+0

Non. Dans le premier cas, x est un pointeur const sur un entier de const. Dans le second cas, x est un pointeur * non-const * vers un entier const. –

+0

Plus précisément, en premier lieu, vous ne pouvez modifier ni x ni * x. Dans le second cas, vous ne pouvez pas modifier x *, mais vous pouvez modifier x. Par exemple, le second pourrait être utilisé pour parcourir un tableau (avec x ++, par exemple), et le premier ne pourrait pas. –

5

Cet exemple est recouvert de manière explicite dans la section de résolution de surcharge, 13.1/3b4:

déclarations de paramètres qui diffèrent seulement par la présence ou l'absence de const et/ou volatils sont équivalent. Autrement dit, les spécificateurs de type const et volatile pour chaque type de paramètre sont ignorés lors de la détermination de la fonction déclarée, définie ou appelée.

[Exemple:

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 exemple]

Ainsi, il est certainement OK.

Questions connexes