2

Suppose you have this very silly code (it's just to make it easy to ask the coming question):

#include <iostream>

class A
{
public:
    A() : m(0) {}

    void showM1( int m )
    {
        std::cout << m << std::endl;
    }

    void showM2()
    {   
        int m = 5;
        std::cout << m << std::endl;
    }

    int m;
};

int main()
{
    A a;
    a.showM1( 5 );
    a.showM2();
}

When I tested, no suprise, it displays 5 and 5. But is this really deterministic? Is the priority ALWAYS given to the local variable (or method parameter) and object attribute comes next?

I'm asking because we renamed some variables in a huge project and just would like to be sure the behaviour is not "undertermined" and could vary on platforms, compilers...

PS: I know this is bad practce and found topics mentioning that the best way is to avoid name conflict (like this one)....

Community
  • 1
  • 1
jpo38
  • 20,821
  • 10
  • 70
  • 151

3 Answers3

6

This is well-defined:

N3337 [basic.scope.hiding]/3: In a member function definition, the declaration of a name at block scope hides the declaration of a member of the class with the same name; see 3.3.7.

m is in a member function definition at block scope, so it hides the class member m.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
1

Class member function local variables are declared in fact in an inner scope of the class scope.

As it is known any declaration of a variable in an inner scope hides a declaration with the same name in the outer scope.

Consider the following code snippet

int x = 1;

namepsace N1
{
    int x = 2;

    struct A
    {
        int x = 3;
    };

    struct B : A
    {
        int x = 4;
        void f( int x = 5 ) { { int x = 6; } }
    };
}

You can imagine the scopes the following way

int x = 1; // global namespace
{
    int x = 2; // namepsace N1
    {
        int x = 3;  // struct A scope
        {
            int x = 4; // struct B scope
            {
                int x = 5; // the funcion f's outer-most scope
                {
                    int x = 6; // function f's inner scope
                    std::cout << x << std::endl;    // outputs 6
                    // here can not output the function parameter x = 5
                    std::cout << B::x << std::endl; // outputs 4
                    std::cout << A::x << std::endl; // outputs 3
                    std::cout << N::x << std::endl; // outputs 2
                    std::cout << ::x << std::endl;  // outputs 1
                }  
            }
        }
    }
}

To test this you can place all the output statements showed above inside the member function definition

    struct B : A
    {
        int x = 4;
        void f( int x = 5 ) 
        { 
            { 
                int x = 6; 

                std::cout << x << std::endl;    // outputs 6
                // here can not output the function parameter x = 5
                std::cout << B::x << std::endl; // outputs 4
                std::cout << A::x << std::endl; // outputs 3
                std::cout << N::x << std::endl; // outputs 2
                std::cout << ::x << std::endl;  // outputs 1
            } 
        }
    };
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

I think the answer is YES, the local variable in a function or block will always cover the other variables with the same name. If you want to reference m of A, use this->m.

Marvin Wang
  • 197
  • 9