Reputation: 2683
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
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