Danny
Danny

Reputation: 2683

C++ Linker complains multiple definition of char* but not std::string

In a big project, I have a .h file which defines a lot of constants within a namespace. Introducing const char* constants results in linker errors complaining of multiple definitions.

ex.h

#include <string>
namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";

    const char* NAME2 = "fred";  // <-- ERROR: multiple definition of `Dv::NAME2'
}

exA.cpp

#include "ex.h"
void aFunction() { printf("this is aFunction\n"); }

exB.cpp

#include "ex.h"    
void aFunction(void);

int main(int argc, char **argv)
{
    aFunction();
    return 0;
}

Compile and Link

g++ -c exA.cpp
g++ -c exB.cpp
g++ exA.o exB.o -o ex
exB.o:(.data+0x0): multiple definition of `Dv::NAME2'
exA.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

The linker error happens if NAME2 is included in the .h file. Why?

If MAX is also a POD (like char[]?), why does the linker not complain of multiple int MAX definitions? (or multiple std::string NAME definitions for that matter?)

I don't understand what's special about char[] in this situation.

Thanks

Upvotes: 4

Views: 2235

Answers (1)

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

According to the C++ Standard (3.5 Program and linkage)

3 A name having namespace scope (3.3.6) has internal linkage if it is the name of

— a non-volatile variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously declared to have external linkage; or

and

4 An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of — a variable; or

In this namespace definition

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";

    const char* NAME2 = "fred";  // <-- ERROR: multiple definition of `Dv::NAME2'
}

(the only) variable NAME2 is not a constant and hence has external linkage.

You could make it as having internal linkage defining it for example with keyword static. For example

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";

    static const char* NAME2 = "fred";
}

Or could define it as a constant

namespace Dv
{
    const int MAX = 10;
    const std::string NAME = "bobo";

    const char * const NAME2 = "fred";
}

Upvotes: 5

Related Questions