61 votes

Ordre d'initialisation des variables statiques de la classe

J'ai une classe A qui possède deux variables statiques. J'aimerais initialiser l'une d'entre elles avec une autre variable statique sans rapport, comme ceci :

#include <iostream>
class A
{
public:
    static int a;
    static int b;
};

int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
    std::cout << A::b << std::endl;

    return 0;
}

La sortie est de 200. Alors, quelqu'un peut-il me dire pourquoi ?

1 votes

Je ne suis pas un expert en langues, mais je pense que dès que vous écrivez A::b dans votre énoncé d'affectation, vous faites le calcul de la portée à l'aide de l'option A et la classe a là. Pour accéder à l'espace global a il devrait être quelque chose comme int A::b = ::a; .

15 votes

@AmirRasulov : Eh bien, jusqu'à présent, 11 personnes (dont moi) pensent que la question montre un effort de recherche, est utile et est claire.

13 votes

@AmirRasulov - C'est un site de questions-réponses. Le seuil d'appartenance d'une question est sa qualité objective (comme Bathsheba l'a souligné), et non la simplicité de la réponse pour vous ou moi.

36voto

StoryTeller Points 6139

C'est correct selon les règles de recherche. [basic.lookup.unqual]/13 dit :

Un nom utilisé dans la définition d'un membre de données statiques de la classe X (après l'identifiant qualifié du membre statique) est recherché comme si le nom était utilisé dans une fonction membre de X. [Note : [class.static.data]. nom était utilisé dans une fonction membre de X. [Note : [class.static.data]. décrit plus en détail les restrictions sur l'utilisation des noms dans la définition d'un membre de données statiques. définition d'un membre statique. -fin de la note]

Étant donné que les a est recherché comme si vous êtes à l'intérieur d'une fonction membre, elle doit trouver le membre A::a premier. L'ordre d'initialisation de A::a y A::b n'affecte pas la recherche, bien qu'elle affecte la qualité du résultat.

4 votes

Quelqu'un peut-il donner les raisons pour lesquelles le comportement a été décidé de cette façon ? Je trouve le code de la question très confus.

1 votes

@Chiel : Facétieusement, je pense que c'est la manière la plus simple et cohérente de résoudre cette ambiguïté.

2 votes

@Bathsheba. Mais la règle crée l'ambiguïté plutôt que de la résoudre d'après ce que je comprends.

16voto

codekaizer Points 4295

Alors, quelqu'un pourrait-il me dire pourquoi ?

Ceci est clairement indiqué dans basic.scope.class/4 C'est moi qui souligne :

Le site portée potentielle d'une déclaration qui s'étend jusqu'à la fin ou au-delà de celle-ci d'une définition de classe également s'étend aux régions défini par son même si les membres sont définis lexicalement. en dehors de la classe (cette inclut des définitions de membres de données statiques les définitions de classes imbriquées et des définitions de fonctions membres, y compris le corps de la fonction membre membre et toute partie de la partie déclarante de ces définitions. qui suit le declarator-id, y compris un clause de déclaration de paramètre et tout argument par défaut).

Ainsi, lorsque vous avez

int A::a = 200;
int a = 100;
int A::b = a; // note the '::' scope resolution operator
              // OUTPUT: 200

a se réfère en fait à A::a parce que le portée de la classe es étendu por A::b .

Contrairement à ce que vous avez :

int A::a = 200;
int a = 100;
int b = a; // note b is not A::b
           // i.e. without the '::', scope resolution operator
           // OUTPUT: 100

a se référerait à l'interface (globale) ::a depuis b ici n'est pas un membre de class A ,
c'est-à-dire aucune extension de la portée de la classe.

0 votes

Merci beaucoup pour votre réponse.

0 votes

@QuantumPlus Votez plutôt en haut à la place . Les commentaires "Merci" sont découragé . En outre, si vous voyez de tels commentaires, vous pouvez les signaler .

8voto

dao leno Points 141

c++draft/class.static

Si un identifiant non qualifié est utilisé dans la définition d'un membre statique à la suite de l'identifiant du déclarant du membre , et la recherche par nom ([basic.lookup.unqual]) trouve que l'identifiant non qualifié fait référence à un membre statique La classe du membre, l'énumérateur ou le type imbriqué de la classe du membre (ou d'une classe de base de la classe du membre), l'identifiant non qualifié est transformé en une expression d'identifiant qualifié dans lequel le spécificateur nested-name nomme la portée de la classe à partir de laquelle le membre est référencé. [Note : Voir [expr.prim.id] pour les restrictions sur l'utilisation des membres de données non statiques et des fonctions membres non statiques. -fin de la note]

Il est dit que l'expression unqualified-id est transformée en une expression qualified-id dans votre situation.

int A::b = a;

Vous pouvez définir qualified-id mais n'a pas de nested-name-specifier comme ceci.

int A::b = ::a;

6voto

Ben Points 4733

Parce que la recherche de nom résout le a como A::a . Si vous voulez faire cela, vous devrez résoudre l'étendue manuellement :

int A::b = ::a;
        // ^ Global scope resolution

Exemple en direct

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X