LostInTheFrequencyDomain
LostInTheFrequencyDomain

Reputation: 1147

C++ : const declrations duplicate symbols issue

I want to avoid #defines in my code. Accordingly, I have the following in a header file :

 #ifndef __GATENAMES__
 #define __GATENAMES__

  namespace GateNames
  {
  const char*   CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";
  const char*   CBSD_GATE_TO_SAS_OUT        = "CbsdGate_SAS_INOUT$o";
  const char*   CBSD_GATE_TO_SAS_IN         = "CbsdGate_SAS_INOUT$i";
  const char*   SAS_GATE_TO_CBSD            = "SasGate_CBSD_INOUT";
  const char*   SAS_GATE_TO_ESC         = "SasGate_ESC_INOUT";
  const char*  SAS_GATE_TO_ESC_OUT         = "SasGate_ESC_INOUT$o";
  const char*  SAS_GATE_TO_ESC_IN         = "SasGate_ESC_INOUT$i";
};
#endif

This header file is included in various places in my code. However, the linker complains that the symbols are multiply defined:

../out/gcc-debug/src/CbsdSim.o:(.data.rel.local+0x0): multiple definition of `GateNames::CBSD_GATE_TO_SAS'

How can I get around this problem? Thanks.

Upvotes: 2

Views: 1583

Answers (2)

marcinj
marcinj

Reputation: 49986

The reason for your linker errors is that non const variables have external linkage, and since you defined them in multiple translation units (by including a header), linker complains.

There are three ways to fix your code. First is to change linkage of your const char* string literals, by making them static. This way they have internal linkage, and each translation unit which includes them will not share them with other translation units - so also linker will not complain:

static const char*   CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";
^^^^^^ 

Second one is to make them const:

const char* const  CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";
            ^^^^^

which is actually quite similar to making them static, they have now internal linkage.

Third way is to declare them in header file and define in one single translation unit.:

// in header file
namespace GateNames
{
extern const char* CBSD_GATE_TO_SAS         ;
};

in some .cpp file:

namespace GateNames
{
const char*   CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";
};

Upvotes: 1

user2100815
user2100815

Reputation:

Firstly, names like this __GATENAMES__, (any name starting with an underscore and an uppercase letter or containing two consecutive underscores) is reserved for the C++ implementation - you shgould not be creating such names in your own code.

Secondly, your constness is a bit mixed up, instead of things like:

const char*   CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";

you want:

 const char *  const CBSD_GATE_TO_SAS            = "CbsdGate_SAS_INOUT";

In other words, it's the pointer that's got to be const to limit the linkage of the pointer, not the thing pointed to (although in this case that also has to be const).

Upvotes: 6

Related Questions