24

I m writing a simple Makefile which looks like this

CC=gcc
CXX=g++
DEBUG=-g
COMPILER=${CXX}
a.out: main.cpp Mail.o trie.o Spambin.o
        ${COMPILER}  ${DEBUG} main.cpp Mail.o trie.o Re2/obj/so/libre2.so

trie.o: trie.cpp
        ${COMPILER}  ${DEBUG} -c trie.cpp

Mail.o: Mail.cpp
        ${COMPILER} ${DEBUG} -c Mail.cpp

Spambin.o: Spambin.cpp
        ${COMPILER} ${DEBUG} -c Spambin.cpp

clean: 
        rm -f *.o

I have a file name config.h which is required in Mail.cpp and Spambin.cpp, so I have #include "config.h" in both Mail.cpp and Spambin.cpp. config.h looks like this:

#ifndef __DEFINE_H__
#define __DEFINE_H__

#include<iostream>

namespace config{
        int On = 1;
        int Off = 0;

        double S = 1.0;
}
#endif

But when I try to compile the code it gives me
Mail.o:(.data+0x8): multiple definition of `config::On'
/tmp/ccgaS6Bh.o:(.data+0x8): first defined here
Mail.o:(.data+0x10): multiple definition of `config::Off'
/tmp/ccgaS6Bh.o:(.data+0x10): first defined here

Can any one help me debug this?

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
Global Warrior
  • 5,050
  • 9
  • 45
  • 75

3 Answers3

52

You can not assign to namespace variables in a header files. Doing that defines the variables instead of just declaring them. Put that in a separate source file and add that to the Makefile and it should work.

Edit Also, you have to make the declarations in the header file extern.

So in the header file the namespace should look like this:

namespace config{
    extern int On;
    extern int Off;

    extern double S;
}

And in the source file:

namespace config{
    int On = 1;
    int Off = 0;

    double S = 1.0;
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Do you mean, "cannot _initialize_ namespace variables in header files"? Even this change is not sufficient. A declaration without an initializer is a definition unless `extern` is explicitly used. – CB Bailey Jan 23 '12 at 12:48
  • @CharlesBailey Remembered about `extern` just the same time you wrote your comment. – Some programmer dude Jan 23 '12 at 12:50
  • @CharlesBailey aren't variables `extern` by default? – Luchian Grigore Jan 23 '12 at 12:51
  • 1
    @LuchianGrigore: They have external linkage by default but that's not the only effect that `extern` has on declarations. – CB Bailey Jan 23 '12 at 12:52
  • @JoachimPileborg: I made the changes as u said but now both the .o compilation says the config is not defined. Can you please tell how the makefile should look. The error is `/Mail.cpp:194: undefined reference to `config::EnvironRecipientVarName /Mail.cpp:195: undefined reference to config::EnvironSenderVarName` – Global Warrior Jan 23 '12 at 13:18
  • @Piyush Add the source file just like the other source files in the Makefile. For example, copy the lines for used for trie.cpp and change the name to your new source file. Remember to add the object file to the command where you link your application. – Some programmer dude Jan 23 '12 at 13:24
  • @JoachimPileborg: just compiled it, its working fine. Forgot to make changes to Makefile. Thanks for help – Global Warrior Jan 23 '12 at 13:25
4

Take a look at Variable definition in header files

You have to put your variable definition, i.e. the value assignment in a source file or protect it with a #ifdef guard for not being defined twice when included in separate source files.

Community
  • 1
  • 1
Bernhard
  • 8,583
  • 4
  • 41
  • 42
3

In your header file, declare const your 3 variables. For example, like this :

#ifndef __DEFINE_H__
#define __DEFINE_H__

#include<iostream>

namespace config{
        const int On = 1;
        const int Off = 0;

        const double S = 1.0;
}
#endif
kolph
  • 41
  • 1
  • I think the problem with this answer is that if you do this, they are no longer _variables_. However as a replacement for `#define` constants, this seems to me like a reasonable way to go. – davidA Oct 21 '15 at 23:54