En C++, quelle est la résolution de la portée ("ordre de priorité") pour les noms de variables ombragées?

EN C++, quelle est la résolution de portée ("ordre de priorité") pour l'ombre noms variables? Je n'arrive pas à trouver une réponse concise en ligne.

Par exemple:

#include <iostream>

int shadowed = 1;

struct Foo
{
    Foo() : shadowed(2) {}

    void bar(int shadowed = 3)
    {
        std::cout << shadowed << std::endl;
            // What does this output?

        {
            int shadowed = 4;
            std::cout << shadowed << std::endl;
                // What does this output?
        }
    }

    int shadowed;
};


int main()
{
    Foo().bar();
}

Je ne vois aucune autre portée où une variable pourrait entrer en conflit. S'il vous plaît, dites-moi si j'en ai manqué un.

Quel est l'ordre de priorité des quatre shadow variables à l'intérieur du bar fonction membre?

16
demandé sur Emile Cormier 2010-05-10 21:29:24

2 réponses

votre premier exemple Produit 3. Vos deuxièmes sorties 4.

La règle générale est que la recherche va de la variable" le plus local "à la variable" le moins local". Par conséquent, la priorité ici est Bloc - > local -> classe - > global.

Vous pouvez aussi accéder à la plupart des versions de la variable Shadow explicitement:

// See http://ideone.com/p8Ud5n
#include <iostream>

int shadowed = 1;

struct Foo
{
    int shadowed;
    Foo() : shadowed(2) {}
    void bar(int shadowed = 3);
};

void Foo::bar(int shadowed)
{
    std::cout << ::shadowed << std::endl; //Prints 1
    std::cout << this->shadowed << std::endl; //Prints 2
    std::cout << shadowed << std::endl; //Prints 3
    {
        int shadowed = 4;
        std::cout << ::shadowed << std::endl; //Prints 1
        std::cout << this->shadowed << std::endl; //Prints 2
        //It is not possible to print the argument version of shadowed
        //here.
        std::cout << shadowed << std::endl; //Prints 4
    }
}

int main()
{
    Foo().bar();
}
31
répondu Billy ONeal 2013-03-18 11:48:19

il devrait être imprimé 3. La règle de base est principalement de faire un retour en arrière à travers le fichier vers la définition la plus récente que le compilateur aurait vue (edit: qui n'est pas sorti de la portée), et c'est ce qu'il utilise. Pour les variables qui sont locales à une classe, vous suivez le même sauf que toutes les variables de classe sont traitées comme si elles étaient définies au début de la définition de classe. Notez que c'est plus ou moins unique de classes. Par exemple, un code donné comme:

int i;

int x() { 
    std::cout << i << '\n'; // prints 0;
    int i=1;
}

même s'il y a i c'est locale à la fonction, la définition la plus récente vu où cout est utilisé, c'est le mondial, c'est ce que l' i dans cette expression se réfère. Si, cependant, ce sont dans une classe:

int i;

class X { 
    void y() { std::cout << i << "\n"; }

    X() : i(2) {}

    int i;
};

Puis cout l'expression renvoie à X::i même si sa définition n'a pas encore été vue quand y est analysée.

5
répondu Jerry Coffin 2010-05-10 17:59:39