Confusion regarding C++ namespace .

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • carbon
    New Member
    • Mar 2014
    • 9

    Confusion regarding C++ namespace .

    Please help me clear my doubts, regarding C++ namespaces.

    For what I know, Namespace defines a scope. Members defined inside namespace have that namespace scope.

    And An object cannot be accessed outside it's scope.

    1. If that is true how are we able to access a namespace member outside the namespace ?
    2. Do member of namespace have global scope ?
    3. If namespace members do not have global scope they should not have been accessible outside the namespace scope, Am I correct ?

    Code:
    namespace n {
    int i = 10;  // scope limited to n namespace
    }
    
    int main(){
    std::cout << n::i; // ???? how we are able to access i here ???
    return 0;
    }
    Please help me clear my doubts.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    First, a member of a namespace cannot be accessed outside the namespace.

    Code:
    nameapace wfc
    {
       int x;
    }
    
    x = 3;  //error! x des not exist
    
    wfc::x = 3;  //OK. x is a member of the wfc name space.
    The namespace attaches a name (wfc) to the int x to get wfc::x. Just like what would happen if wfc was a struct.
    However, wfc is not a struct. (Even more C++ smoke and mirrors).

    Now if the wfc namespace is not in the file being compiled, then:

    Code:
    wfc::x = 3;  //OK. there is a wfc namespace
    But this:

    Code:
    x = 3;   //error. x does not exist.
    But if you tell the compiler that you are using the wfc namespace:

    Code:
    using namespace wfc;
    x = 3;  //OK. x is a member of wfc namespace
    If you want to add y to the wfc namespace, you just code:

    Code:
    namespace wfc
    {
       int y;
    }
    You don't go looking for the namespace wfc declaration. A namespace is not a struct. There is no one place that contains all the wfc members. Things are in the wfc namespace because you say so.

    If you want to delete y from the wfc namespace, just delete the above code.

    The primary purpose of the code in this reply is to prevent redefinition errors when code written by carbon is merged in with code written by wfc.
    Last edited by weaknessforcats; Aug 5 '14, 12:11 AM. Reason: fix a bug in my reply

    Comment

    • carbon
      New Member
      • Mar 2014
      • 9

      #3
      Thanks buddy ;) Ok I got it . There is another doubt that I would like to clear.

      Do Namespace names (identifier) have global scope with external linkage ?

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        Linkage???

        Again, a namespace is not a struct or a variable so the namespace has no linkage. However, the members are variables and they have the linkage they are supposed to have based on where they are defined. If you define the namespace members globally, then they have global scope. If the namespace members are declared statically, then those members are static.

        Using namespaces is to prevent compile errors when merging various pieces of code. Once I had to use Microsoft sockets and when I added that code to mine I got errors on GROUP. Turns out there is a group of sockets just like in my code there was a group of managers. Took me a month to remove GROUP from my program and name it something else just so the code would compile. Had the code been in C++ using namespaces it would have compiled the first time.

        However, the most powerful use of namespaces is the anonymous namespace:

        Code:
        namespace
        {
             int x;
        }
        The only access to x will be in the file containing the above code. That means that the name "x" is hidden except from the code in this file.

        This allows you to write functions in this file to access x and these functions can be called from anywhere else but the name "x" is hidden. This is fundamental data hiding and this is important because the rest of the program does not know how the data is implemented. You can completely redesign the namespace and the code in this file, recompile and relink, and your program has no idea a redesign was implemented. This would not be possible if the name "x" were scattered all over the place.

        Comment

        • carbon
          New Member
          • Mar 2014
          • 9

          #5
          @weaknessforcat Thanks.

          Code:
          #include <iostream>
          #include <cstdlib>
          
          namespace A {
          	int a = 10;
          	void get_value(){ std::cout << "a = " << a << std::endl; }
          }
          
          namespace B {
          	int b;
          	void get_value(){ std::cout << "b =" << b << std::endl; }
          }
          
          // using namespace A; if used here generate compilation error 
          void set_B();
          
          int main(){
          
          	using namespace A; // if using-directive is used here no compilation error is generated 
          	get_value();
          	set_B();
          
          	system("PAUSE");
          	return 0;
          }
          
          void  set_B(){
          	using namespace B;
          	b = 15;
          	get_value();
          
          }
          if using-directive using namespace A; is used outside main() then gcc generates a compilation error "call of overloaded 'get_value()' is ambiguous". Which I understand ,as the using namespace A; introduces A::get_value() to the global-namespace and using-directiveusing namespace B; located inside function set_B(), also introduce the B::get_value() function to the global-namespace. Hence the conflict occurs.

          What I don't understand is if using namespace A; using-directive statement is put inside main(), program compiles successfully. Why compiler didn't showed any error. Even if we used the using-directive statement inside the main() the A::get_value() was introduced inside the global-namespace which should have caused conflict with the B::get_value().



          I'm teaching myself C++ language. There are lots questions that I would like to ask. So should I create new relevant threads or continue with this one ?

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            The compiler is processing a function. In this case main where you call get_value(). There is no get_value(). f course there is A::get_value() and B::get_value(). BU these are not called in main(). Therefore the call to get_value() is an error. However, you race in and code using namespace A; before the call which causes the compiler to search the A namespace and finds A::get_value() so it calls that.

            There is a danger here. If you are using namespace A and there is a get_value() function in the global namespace, then the compiler doesn't know which one to call so your compiles fails in ambiguous call to get_value().

            You are supposed to code A::get_value or ::get_value() to remove any ambiguity and this makes the using namespace directive pointless. In fact, the using directive is considered sloppy.

            This thread is considered complete if the questions in your original post are answered. Additional questions should be put in new threads.

            Comment

            • carbon
              New Member
              • Mar 2014
              • 9

              #7
              Sorry but this doesn't answer my question. I think you didn't get what I'm trying to ask.

              using namespace A; if used outside the main() causes "call of overloaded 'get_value()' is ambiguous" compilation error. Where as it doesn't cause any compilation error when used inside the main().

              Here two things are to be considered
              using namespace A; // inside or outside main()
              using namespace B; // inside function set_B()

              In both the cases ( using namespace A either outside or inside main() ) get_value() function from A and B namespace are brought into global namespace, in one case it causes compilation error and in other case no error why ?

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                When using namespace A is inside main(), it applies only to main(). Therefore, the get_value() is the one in A.

                When using namespace A outside main(), there is no issue in main(). The get_value called is the one in A. However, when compiling set_B() does the compiler use A::get_value() or B::get_value introduced by the using namespace B inside that function?

                This is exactly the sloppy code I referred to in Post #6. The preferred style is to use A::get_value() or B::get_value() as needed because there is no ambiguity possible.

                Failing that, the next preferred style is to place the using namespace declaration at the beginning of each function to limit ambiguity to just that function.

                Comment

                • carbon
                  New Member
                  • Mar 2014
                  • 9

                  #9
                  "When using namespace A is inside main(), it applies only to main(). Therefore, the get_value() is the one in A."

                  But according to cpp standard members will be introduced into the enclosing namespace which in this case is global namespace.

                  From Cpp 98 standard ..
                  7.3.4 : A using-directive specifies that the names in the nominated namespace can be used in the scope in which the usingdirective
                  appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. A using-directive does not add any members to the declarative region in which it appears.


                  PS: How do I quote lines from a previous reply ?

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    7.3.4 : A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using directive
                    appears
                    after the using-directive.
                    It means scope. A using directive in a scope, like a function, is limited to that scope.

                    However, if you have inner scopes in that function, the using directive is valid there also because outer scopes enclose inner scopes.

                    That is why the using directive in the global scope is so bad. It is valid in every scope in the file whether or not it causes ambiguous name resolution.

                    Comment

                    Working...