Using namespace across multiple files

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • PetrH
    New Member
    • Oct 2009
    • 4

    Using namespace across multiple files

    The problem I have is basically the same as 'greentype' mentions at
    <Link Removed>

    I'm sharing variables through namespaces and a problem arises when I try to put my function definitions into a separate file.

    Consider the following example, where I want to pass variable 'i', defined
    in the main code, to the function a():

    ------------------------------
    *** nn.h: ***
    #ifndef _NN_H_
    #define _NN_H_

    namespace nn {
    int i;
    }
    #endif

    *** main.cpp ***
    #include <iostream>
    #include "nn.h"
    using namespace std;
    using namespace nn;

    void a();

    int main()
    {
    i=5;
    a();
    }

    void a()
    {
    using namespace std;
    using namespace nn;

    i++;
    cout << "i = " << i << endl;
    }
    ------------------------------

    But now if I put the definition of a() into a separate file ...

    ------------------------------
    *** a.cpp ***
    #include <iostream>
    #include "nn.h"

    void a()
    {
    using namespace std;
    using namespace nn;

    i++;
    cout << "i = " << i << endl;
    }
    ------------------------------

    ... then I get 'multiple definition' error when linking (g++ main.cpp
    a.cpp -o main). If I make 'i' declaration in the header file 'extern' (as
    suggested in other forums), I get 'undefined reference' error. I can compile when 'i' is declared as const in the header, but that's not what I want.

    Any suggestions greatly appreciated.
  • newb16
    Contributor
    • Jul 2008
    • 687

    #2
    linker complains because 'i' is delared, but never defined.
    Declare it with extern in header, and define it (without 'extern') only once in some .cpp file
    Code:
    // in some .cpp file
    namespace nn {
    int i;
    }

    Comment

    • Banfa
      Recognized Expert Expert
      • Feb 2006
      • 9067

      #3
      This is nothing to do with namespaces. It is because you have declared i without the extern in the header file. The compiler treats this as a definition so the variable is defined in every source file you include the header in and you have multiple definitions of i.

      By using the extern keyword

      extern int i;

      you are only declaring a, that is you inform the compiler that a variable a exists somewhere. You will then need to actually define a

      int i;

      in one of the source files.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        Originally posted by Banfa
        extern int i;

        you are only declaring a, that is you inform the compiler that a variable a exists somewhere. You will then need to actually define a

        int i;

        in one of the source files.
        Mostly correct.

        Code:
        extern int i;
        declares that there is an int i with external linkage. It may be in this file or it may be in some other file.

        For example, this is OK:
        Code:
        extern int i;
        int main()
        {
            i = 10;
        }
        int i = 0;
        Code:
        extern int i = 0;
        defines (creates) a variable int i with external linkage that has a value of 0. Other files can use this int i by coding extern int i.

        When you place a value on your extern you actually create the variable. This is how you create sharable const values:

        Code:
        extern const int i = 10;
        This creates a const int with a value of 10 that has external linkage. Other files can access this variable by coding:

        Code:
        extern const int i;

        Comment

        • PetrH
          New Member
          • Oct 2009
          • 4

          #5
          Thank you guys for your replies, unfortunately none of that helps:

          TO: newb16 & banfa: As I said, once I declare 'i' in the header as 'extern' and define it in main.cpp, a() in a.cpp doesn't know about it (undefined reference). And if I define 'i' in a() too, than I'm creating another variable, whereas I want to share (and change, if needed) the original one (defined in main.cpp).

          TO: weaknessforcats : As I said, I don't want 'i' to be const. I want to be able to define it in main.cpp and share & change it (i++) in a.cpp. Which I can do as long as a() is in main.cpp, but not if I put it into a separate file, a.cpp.

          Thanks,

          Petr

          Comment

          • PetrH
            New Member
            • Oct 2009
            • 4

            #6
            I see. Thank you guys. So if I understand this, the only way to get it to work is to make 'i' global, i.e. put the definition
            'namespace nn { int i=5;}' in main.cpp, above int main() (and make the declaration 'extern', of course). But notice that in the original example (where function a() is in the SAME FILE as main()), 'i' was not global - I defined it within main(), yet still was able to share it with, and modify in, a() through the namespace. That is the framework I would like to retain, because I can't really make 'i' global, since it (and other variables I have and need to share) is CALCULATED in main() - I don't know their values in advance.

            Petr

            Comment

            • donbock
              Recognized Expert Top Contributor
              • Mar 2008
              • 2427

              #7
              Originally posted by PetrH
              ... But notice that in the original example (where function a() is in the SAME FILE as main()), 'i' was not global - I defined it within main(), yet still was able to share it with, and modify in, a() through the namespace. That is the framework I would like to retain, because I can't really make 'i' global, since it (and other variables I have and need to share) is CALCULATED in main() - I don't know their values in advance.
              If you want the same variable i to be accessible from two or more source files then it either has to be a global variable or you need to pass a pointer-to-i to function a(). This is not a namespace issue.

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                Originally posted by PetrH
                But notice that in the original example (where function a() is in the SAME FILE as main()), 'i' was not global - I defined it within main(), yet still was able to share it with, and modify in, a() through the namespace. That is the framework I would like to retain, because I can't really make 'i' global, since it (and other variables I have and need to share) is CALCULATED in main() - I don't know their values in advance.
                You have your terminology wrong.

                In your original example i was global, but because you only had 1 source file that wasn't obvious. Any variable defined at file scope without the static specifier has global linkage, this is how you defined i and this is what caused the initial problem when you put that definition into 2 source files (though inclusion).

                You don't define i in main() in your original example. You assigned to it. You still can with the proposed solution.

                I can't quite tell what it is that makes you think i can't be global since it is and has been throughout all code examples and suggested solutions in this thread.

                Of course you should be avoiding use of global variables in C++ (and in C for that matter but it a little harder with C), they are very bad practice.

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  Originally posted by PetrH
                  I see. Thank you guys. So if I understand this, the only way to get it to work is to make 'i' global, i.e. put the definition
                  'namespace nn { int i=5;}' in main.cpp, above int main() (and make the
                  I'm sorry. I didn't understand that you are using namespaces.

                  When you use a namespace you have to understand that a namespace is not like a struct. That is, there is no single place you can go to see what's in the namespace. It's what they call an open-ended definition->Things are in the namespace if you say so.

                  In this case in a .cpp file, say Data.cpp put your namespace that defines the int:

                  Code:
                  Data.cpp
                  namespace Stuff
                  {
                      int i = 0;
                  }
                  Then write a header file Data.h:

                  Code:
                  namespace Stuff
                  {
                      extern int i;
                  }
                  Then in main.cpp you can access the int:

                  Code:
                  #include <Stuff.h>
                  int main()
                  {
                      cout << Stuff::i;
                  }
                  Of course this assumes that Data.cpp and main.cpp are both in your build.

                  If you read up on anonymous namespaces you will find out how to do away with the name Stuff altogether.

                  Comment

                  • PetrH
                    New Member
                    • Oct 2009
                    • 4

                    #10
                    Thank you guys. I get it now.

                    Comment

                    Working...