dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10

Thread: Namespaces

Hybrid View

  1. #1
    Join Date
    Mar 2003
    Posts
    29

    Unhappy Namespaces

    Hi,

    I am trying to understand the usage of namespace. I have written the below simple code which compiles with out any issues. But while linking I am getting the error "dummain.obj : error LNK2005: "class dum oss:" (?d@oss@@3Vdum@@A) already defined in dumma.obj" . If I dont use namespae, it gets linked. Could any please tell me what I am doing wrong and how can I fix so that I can use namespae.

    Thanks,
    Abbas

    Code:
    //File Name "dummain.cpp"
    #include "dumma.h"
    using namespace oss; //If I remove this line and add "dum d" code works fine.
    
    int main(void)
    {
        d << "Testing";
        return 0;
    }
    Code:
    //File Name "dumma.h"
    #include <stdio.h>
    
    class dum{
        public:
        void operator << (char *);
    };
    
    namespace oss{
        dum d;
    }
    Code:
    //File Name "dumma.cpp"
    #include "dumma.h"
    
    void dum::operator <<(char *inp)
    {
       printf("%s\n",inp);
    }

  2. #2
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,116

    Re: Namespaces

    Namespaces are typically used to holde NAMES (classes, etc) rather than objects. Look at the following:


    Code:
    //File Name "dummain.cpp"
    #include <stdio.h>
    #include "dumma.h"
    
    using namespace oss; // bring NAMES within oss in, so we dont have to be explicit
    
    int main(void)
    {
        dum d;
        d << "Testing";
        return 0;
    }
    
    
    Code:
    //File Name "dumma.h"
    namespace oss{
     class dum{
        public:
        void operator << (char *);
    };
    
    }
    
    
    //File Name "dumma.cpp"
    #include <stdio.h>
    #include "dumma.h"
    
    void oss::dum::operator <<(char *inp)
    {
       printf("%s\n",inp);
    }
    Hope this helps...
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  3. #3
    Ejaz's Avatar
    Ejaz is offline Elite Member Power Poster
    Join Date
    Jul 2002
    Location
    Lahore, Pakistan
    Posts
    4,211

    Re: Namespaces

    The usage of the namespace has already been elaborated, but if you want to put your global variables in a namespace, then you can create another file to create the namespace, rather then mixing the part of the namespace with any of the class, so that you don't get linking errors like these in case of multiple inclusions, like

    Code:
    // File: MyNameSpace.h
    
    #include "dumma.h"
    namespace oss
    {
        dum d;
    }
    
    // *************************
    // File: Dumma.h
    #include <stdio.h>
    
    class dum{
        public:
        void operator << (char *);
    };
    
    // *************************
    // File: Dumma.cpp
    #include "dumma.h"
    
    void dum::operator <<(char *inp)
    {
       printf("%s\n",inp);
    }
    
    // *************************
    // File: main.cpp
    #include "mynamespace.h"
    using namespace oss; 
    
    int main(void)
    {
        d << "Testing";
        return 0;
    }
    Last edited by Ejaz; October 3rd, 2004 at 09:02 AM.

  4. #4
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,116

    Re: Namespaces

    Ejaz.. your post is incorrect!

    Putting a variable within a namespace does NOT effect its linkage!!!!

    It you put a variable in a namespace in a header, and then include the header in multiple compilation unites, you will multiply define the variable.

    You must use extern linkage on variables within a namespace [within a header]. and then be sure to actually define the variable in one and only one compilation unit!!!!
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  5. #5
    Ejaz's Avatar
    Ejaz is offline Elite Member Power Poster
    Join Date
    Jul 2002
    Location
    Lahore, Pakistan
    Posts
    4,211

    Re: Namespaces

    Quote Originally Posted by TheCPUWizard
    Ejaz.. your post is incorrect!

    Putting a variable within a namespace does NOT effect its linkage!!!!

    It you put a variable in a namespace in a header, and then include the header in multiple compilation unites, you will multiply define the variable.

    You must use extern linkage on variables within a namespace [within a header]. and then be sure to actually define the variable in one and only one compilation unit!!!!
    You are right TheCPUWizard, sorry for that, I don't know where I left my mind today, I really should have a some break now. Thanx for the correction anyway.

  6. #6
    Join Date
    Mar 2003
    Posts
    29

    Re: Namespaces

    TheCPUWizard,

    Could you pleae clarify indetail. Now after implementing Ejaz method the code started working!

    Reason I prefer Ejaz method, because I can implement my code something like "cout".

    Thanks,
    Abbas

  7. #7
    Join Date
    Mar 2002
    Location
    St. Petersburg, Florida, USA
    Posts
    12,116

    Re: Namespaces

    As soon as you include "MyNameSpace.h" in TWO (or more) files, you are back to the same situation that you started. If you want to declare a global variable withing the scope of a namespace, the same rules apply as variables in the global namespace

    Code:
    // SomeHeader.h
    
    #ifdef DEFINE_NS_GLOBALS
    #define LINKAGE
    #undef DEFINE_NS_GLOBALS
    #else
    #define LINKAGE extern
    #endif
    
    namespace MySpace
    {
           LINKAGE  int MyGlobalVar;
    }
    
    
    // SomeLibrary.c
    #define DEFINE_NS_GLOBALS
    #include <SomeHeader.h>
    
    
    // File1.c
    #include <SomeHeader.h>
    
    int f()
    {
         ++ MySpace::MyGlobalVar;
    }
    
    // File2.c
    #include <SomeHeader.h>
    
    using namespace MySpace;
    
    int g()
    {
         --MyGlobalVar;
    }
    
    // File3.c
    #include <SomeHeader.h>
    
    using MySpace::MyGlobalVar;
    
    int h()
    {
        MuGlobalVar = 0;
    }
    Last edited by TheCPUWizard; October 3rd, 2004 at 11:20 AM.
    TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
    2008, 2009,2010
    In theory, there is no difference between theory and practice; in practice there is.

    * Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions
    * How NOT to post a question here
    * Of course you read this carefully before you posted
    * Need homework help? Read this first

  8. #8
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652

    Re: Namespaces

    And just in case...the following might help in understanding namespaces in general...

    Namespaces allow you to group a set of global classes, objects and/or functions under one name. To say it somehow, they serve to split the global scope in sub-scopes known as namespaces.

    The form of a namespaces is:
    Code:
    namespace identifier
    {
      namespace-body
    }
    where identifier is any valid identifier and namespace-body is the set of classes, objects and functions that are included within the namespace. For example:
    Code:
    namespace general
    {
      int a, b;
    }
    In this case, a and b are normal variables integrated within the general namespace. In order to access these variables from outside the namespace you have to use the scope operator ::.

    For example, to access the previous variables you would have to put:
    Code:
    general::a
    general::b
    The functionality of namespaces is specially useful in case that there is a possibility that a global object or function can have the same name than another one, causing a redefinition error. For example:
    Code:
    #include <iostream>
    
    namespace first
    {
      int var = 5;
    }
    
    namespace second
    {
      double var = 3.1416;
    }
    
    int main()
    {
      std::cout << first::var << std::endl;
      std::cout << second::var << std::endl;
    
      return 0;
    }
    In this case two global variables with the var name exist, one defined within namespace first and another one in second. No redefinition errors thanks to namespaces.

    The using directive followed by namespace serves to associate the present nesting level with a certain namespace so that the objects and functions of that namespace can be accesible directly as if they were defined in the global scope. Its utilization follows this prototype:
    Code:
    using namespace identifier;
    Thus, for example:
    Code:
    #include <iostream>
    
    namespace first
    {
      int var = 5;
    }
    
    namespace second
    {
      double var = 3.1416;
    }
    
    int main()
    {
      using namespace second;
    
      std::cout << var << std::endl;
      std::cout << (var*2) << std::endl;
    
      return 0;
    }
    In this case you have been able to use var without having to precede it with any scope operator.

    You have to consider that the sentence using namespace has validity only in the block in which it is declared (understanding as a block the group of instructions within key brackets {}) or in all the code if it is used in the global scope. Thus, for example, if you had intention to first use the objects of a namespace and then those of another one you could do something similar to:
    Code:
    #include <iostream>
    
    namespace first
    {
      int var = 5;
    }
    
    namespace second
    {
      double var = 3.1416;
    }
    
    int main()
    {
      {
        using namespace first;
        std::cout << var << std::endl;
      }
    
      {
        using namespace second;
        std::cout << var << std::endl;
      }
    
      return 0;
    }
    One of the best examples about namespaces is the standard C++ library itself. According to ISO C++ standard, the definition all the classes, objects and functions of the standard C++ library are defined within namespace 'std'.

    Almost all compilers, even those complying with ISO standard, allow the use of the traditional header files (like iostream.h, stdlib.h, etc). Nevertheless, the ISO standard has completely redesigned these libraries taking advantage of the template feature and following the rule to declare all the functions and variables under the namespace 'std'.

    The standard has specified new names for these "header" files, basically using the same name for C++ specific files, but without the ending '.h'. For example, 'iostream.h' becomes 'iostream'.

    If you use the ISO-C++ compliant include files you have to bear in mind that all the functions, classes and objects will be declared under the 'std' namespace. For example:
    Code:
    #include <iostream>
    
    int main()
    {
      std::cout << "Hello world" << std::endl;
    
      return 0;
    }
    Although it is more usual to use using namespace and save you to have to use the scope operator :: before all the references to standard objects:
    Code:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
      cout << "Hello world" << endl;
    
      return 0;
    }
    If you take a look at the last thing I wrote you will see what I meant. If you put a global using directive than you can access every variable, function, class, template etc. from that namespace in this case 'std'. That means of course that all the variables, function etc. in this namespace become global objects too. Everywhere in your code you can access the content of this namespace without the scope operator ::. That's of course not the real purpose of a namespace. Like I mentioned namespaces are designed to seperate variables, functions etc. But as I said in case of the STL is is more usual to declare the whole namespace...of course if you only use e.g. the string template you don't need to map the whole namespace... there you only use the using directive as follows:
    Code:
    using std::string;
    This maps only the string template into your applications' namespace instead the whole 'std' namespace...

    The following shows you the four different methods to map a namespace...
    Code:
    // Using the full member name, including the namespace it belongs to:
    std::cout << "Hello World";
    
    
    // By taking advantage of Using-Declarations:
    using std::cout;                             // This declares cout in the current
                                                 // scope as synonym for std::cout
    cout << "Hello World";
    
    
    // By taking advantage of Using-Directives:
    using namespace std;                         // Which specifies that the current
                                                 // scope can refer to names in the
                                                 // 'std' namespace without using
                                                 // full qualifiers. This is mostly
                                                 // used when porting legacy code.
    cout << "Hello World";
    
    
    // Using aliases:
    namespace X
    {
      namespace Y
      {
        class Z { ... };
      }
    }
    
    X::Y::Z                                      // The full qualifier for 'Z' is
                                                 // 'X::Y::Z'
    
    namespace w = X::Y;                          // This declares 'w' as an alias for
                                                 // namespace 'X::Y'
    
    w::Z                                         // Access 'Z' using 'w::Z'

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)