简体   繁体   中英

C++ namespace and const variable

I compile those files as single program with Visual studio 2019 in win10

My project have just two source files:

/**** a.cpp ****/

namespace pers{
    const int LEN = 5;
}

/**** b.cpp ****/

namespace pers {
    const int LEN = 5;
}

int main() {
    return 0;
}

It can be compiled successfully.But I dont konw why? I defined LEN twice!!

so, I delete the const :

/**** a.cpp ****/

namespace pers{
    int LEN = 5;
}

/**** b.cpp ****/

namespace pers {
    int LEN = 5;
}

int main() {
    return 0;
}

Now it doesn't work! So, my question is what happend? const variable in diffierent source files can be defined twice or more (means NO multi-definition error) .

Meanwhile, compiler will throw "multi-definition error" if do this:

namespace pers {
    const int LEN = 5;
    const int LEN = 5; // multi-definition error

    const int LEN2 = 10;
}
namespace pers {
    const int LEN2 = 10; // multi-definition error
}


int main() {
    const int a = 10;
    const int a = 10; // multi-definition error

    return 0;
}

Let's see on case by case basis what is happening:

Case 1

Here we consider:

a.cpp

namespace pers{
    const int LEN = 5; //this LEN has internal linkage and is different from the LEN defined in b.cpp
}

b.cpp

namespace pers {
    const int LEN = 5; //this LEN has internal linkage and is different from the LEN defined in a.cpp
}

int main() {
    return 0;
}

It can be compiled successfully.But I dont know why?

This is because LEN has internal linkage meaning its use is limited to a single translation unit and so the LEN in a.cpp and b.cpp are not the same . This can be see from basic.link which states:

A name having namespace scope has internal linkage if it is the name of

  • a non-inline variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or

And also,

When a name has internal linkage, the entity it denotes can be referred to by names from other scopes in the same translation unit .

(emphasis mine)

This means the LEN In a.cpp and the LEN in b.cpp are distinct from each other and so there is no multiple definition error.


I defined LEN twice!!

As explained above, you're not defining the same LEN twice. They are different from each other because they have a namespace scope and are const qualified.

Case 2

Here we consider:

a.cpp

namespace pers{
    int LEN = 5; //this LEN has external linkage and is the same a the LEN in b.cpp
}

b.cpp

namespace pers {
    int LEN = 5; //this LEN has external linkage and is the same LEN as in a.cpp
}

int main() {
    return 0;
}

In this case, LEN has external linkage meaning both the LEN in a.cpp and b.cpp are the same and since you're defining the same name twice, you're violating ODR.

Case 3

Here we consider:

namespace pers {
    const int LEN = 5; //OK, define `LEN` with internal linkage for the first time 
    const int LEN = 5; // error because you're defining the same LEN with internal linkage for the second time in the same TU

    const int LEN2 = 10;
}



int main() {
    const int a = 10;  //define a for the first time in this TU
    const int a = 10; // error because you're defining the same a for the second time in the same TU

    return 0;
}

In this case 3, you're definining the same LEN twice and hence getting the mentioned error. We cannot define any entity more than once in the same translation unit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM