2009-08-21 7 views
6
struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    return A::B::b; 
} 

Le code ci-dessus se compile. Cependant si vous allez par le livre efficace de C++ par Scott Myers (pg 14); Nous avons besoin d'une définition de a en plus de la déclaration. Quelqu'un peut-il expliquer pourquoi c'est une exception?en utilisant un const statique dans une structure/classe

+1

Le code _does_ contient une définition de 'a'. –

+2

Non, il ne contient pas de définition. –

+1

@Henk. Pas vraiment. Essayez de passer l'adresse de 'a' ou 'b' à une fonction et voyez quel message le compilateur génère! –

Répondre

18

Les compilateurs C++ permettent aux entiers constants statiques (et aux entiers uniquement) d'avoir leur valeur spécifiée à l'emplacement où ils sont déclarés. Ceci est dû au fait que la variable n'est essentiellement pas nécessaire et ne vit que dans le code (elle est généralement compilée).

D'autres types de variables (tels que static const char *) ne peuvent généralement pas être définis là où ils sont déclarés et nécessitent une définition distincte. Pour une toute petite explication supplémentaire, sachez que l'accès à une variable globale nécessite généralement de faire une référence d'adresse dans le code de niveau inférieur. Mais votre variable globale est un entier dont la taille correspond généralement à la taille d'une adresse, et le compilateur se rend compte qu'il ne changera jamais, alors pourquoi s'embêter à ajouter l'abstraction du pointeur?

+0

+1, bonne réponse. Mais que faire si les entiers 'const'? Pouvons-nous spécifier leur valeur en classe? – Alcott

+0

pas "entiers", juste l'expression constante – czxyl

18

Par des règles vraiment pédantes, oui, votre code a besoin d'une définition pour cet entier statique. Mais par des règles pratiques, et ce que tous les compilateurs implémentent parce que c'est ainsi que les règles de C++ 03 sont prévues - non, vous n'avez pas besoin d'une définition. Les règles pour ces entiers constants statiques sont destinées à vous permettre d'omettre la définition si l'entier est utilisé uniquement dans des situations où une valeur est immédiatement lue, et si le membre statique peut être utilisé dans des expressions constantes.

Dans votre déclaration de retour, la valeur du membre est immédiatement lue, vous pouvez donc omettre la définition du membre de l'entier statique statique si c'est la seule utilisation. Toutefois, la situation suivante nécessite une définition:

struct A { 
    static const int a = 5; 

    struct B { 
     static const int b = a; 
    }; 

}; 

int main() { 
    int *p = &A::B::b; 
} 

Aucune valeur n'est lue ici, mais l'adresse est prise en compte. Par conséquent, l'objectif de la norme C++ 03 est que vous devez fournir une définition pour le membre comme suit dans un fichier d'implémentation.

const int A::B::b; 

Notez que les réelles règles figurant dans le 03 C++ standard dit qu'une définition n'est pas nécessaire que lorsque la variable est utilisée lorsque une expression constante est nécessaire . Cette règle, cependant, si elle est strictement appliquée, est trop stricte. Cela vous permettrait seulement d'omettre une définition de situation comme tableau-dimensions - mais nécessiterait une définition dans des cas comme une déclaration de retour. Le rapport de défaut correspondant est here.

Le libellé de C++ 0x a été mis à jour pour inclure cette résolution de rapport de défaut et pour permettre l'écriture de votre code.

+0

Est-ce que cela signifie que Walt W a tort quand il dit: "Les compilateurs C++ permettent de définir des entiers constants statiques (et entiers uniquement) à l'endroit où ils sont déclarés"? Je pensais comme lui que le "static const int a = 5;" déclaration était à la fois déclaration et définition. Si je comprends bien, ce n'est qu'une déclaration sans définition et le A :: a ne peut être utilisé que dans des cas très spécifiques. Je suis intesrested dans le dernier mot ... – neuro

+0

Oui, il a tort aussi. Ce n'est qu'une déclaration - ce n'est pas une définition. Si vous y faites référence dans les cas où la valeur n'est pas immédiatement lue, une définition est nécessaire. Vous semblez avoir raison dans votre commentaire. –

+0

Mieux? Je suppose que ce n'était pas l'utilisation technique de "définition" –

0

En général, la plupart (et récent) compilateurs C permettent de ints const statiques

Vous venez de la chance, peut-être pas. Essayez le compilateur plus ancien, tel que gcc 2.0 et il vous punira avec véhémence avec un message d'erreur moins-que-joli.

1

Cependant, si vous essayez l'opérande ternaire sans « définir » consts statiques, vous obtenez une erreur de linker dans GCC 4x:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795

Ainsi, bien que des constructions comme int k = A::CONSTVAL; sont illégales dans la norme actuelle, ils sont soutenus. Mais l'opérande ternaire ne l'est pas. Certains opérateurs sont plus égaux que d'autres, si vous obtenez ma dérive :)

Tellement pour les règles «laxistes». Je vous suggère d'écrire un code conforme à la norme si vous ne voulez pas de surprises.

Questions connexes