C++ Namespace member access in different files how to? how "namespace std" implemented?

11,022

Solution 1

Include guards will work only during compile time, but the error is at link time. This is because the sample.h is included in both compilation units and a variable N1::b is created in both.
If you really want a variable (not a const) you have to declare it as extern in the header, and create a memory location for it in a separate compilation unit:

// sample.h
#ifndef N1
#define N1
namespace N1 {
    extern int b;
}
#endif

// sample.cpp
#include "sample.h"
namespace N1 {
    int b = 80;
}

Solution 2

Its not a problem of #ifndef guard.

Use extern in the header file as:

//sample.h
namespace N1
{
    extern int b; //extern is MUST!

    //DONT WRITE : extern int b = 80;
}

Then define it in .cpp file as:

//sample.cpp
namespace N1
{
    int b = 80;  //initialization should be here
}

Solution 3

Isn't it just a case of a missing ifdef or pragma once in the sample.h file?

Solution 4

Every time you #include sample.h into a .cpp module it will create a new linker record for b giving you multiple defines on the link[1].

The int should be defined in sample.cpp, or somewhere else and simply extern int b in sample.h.


[1] some linkers will ignore this and you'll be able to link OK, but most of the time it will generate errors.

Solution 5

Your issue is that you have a definition of an object with external linkage in a header file which is included in two separate compilation units. The issue is independent of namespaces as such.

One solution is to make the header file include a declaration only, (e.g. see below) and place the definition on a single source file.

// sample.h
namespace N1
{
    extern int b;
}

// sample.cc
namespace N1
{
    int b = 80;
}

Another solution is to give the object internal linkage, although this will mean that you have multiple objects called b but this may not be an issue. For example, if b is supposed to be constant then this would work because const objects have internal linkage by default.

// sample.h
namespace N1
{
    const int b = 80;
}
Share:
11,022
osdevkid
Author by

osdevkid

I am a computer student.

Updated on June 06, 2022

Comments

  • osdevkid
    osdevkid almost 2 years

    I have declared the below namespace in sample.h

    // namespace with identifier
    namespace N1
    {
        int b = 80;
    }
    

    sample1.cpp use the above namespace declaration

    #include <iostream>
    #include "sample.h"
    
    using namespace std;
    using namespace N1;
    
    int main(void)
    {
        cout << "b (in main) = " << b << endl;
          foo(); //written in sample2.cpp
          return 0;
    }
    

    sample2.cpp also use the namespace declared in sample.h

    #include <iostream>
    #include "sample.h"
    
    using namespace std;
    using namespace N1;
    
    void foo(void)
    {
        cout << "b = " << b << endl;
    }
    

    when I compiled, I got the below errors

    $> g++ sample1.cpp sample2.cpp
    /tmp/ccB25lEF.o:(.data+0x0): multiple definition of `N1::b'
    /tmp/cchLecEj.o:(.data+0x0): first defined here
    

    Let me know how to resolve and how "namespace std" implemented to avoid this problem ?