user2513924
user2513924

Reputation: 2250

C++ global namespace members already defined error

I'm trying to make a namespace and its members available globally however I am running into already defined errors.

Settings.h

#pragma once
#include "boost/property_tree/json_parser.hpp"
#include <string>

using json = boost::property_tree::ptree;
namespace Settings {

    extern std::string settingsPath;
    extern json settings;

    extern void init();
    extern void readSettings();
    extern void writeSettings();
};

Settings.cpp

#pragma once

#include "Settings.h"

using json = boost::property_tree::ptree;

namespace Settings {

    void init() {

    }

    void readSettings() {

    }

    void writeSettings() {

    }
};

I am forward declaring the Settings namespace and members and using extern. I have no idea what I'm doing wrong. Please could someone point out the error here.

Thanks

Edit: The actual error messages:

Error   LNK2005 "class std::basic_string<char,struct std::char_traits<char>,class 
        std::allocator<char> > Settings::settingsPath" (?settingsPath@Settings@@3V?$
        basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@A) already defined in 
        AmalgamService.obj  Amalgam F:\Dropbox\CPP\Visual Studio Projects\Amalgam\Amalgam\
        main.obj    1   

And repeat for all members of the namespace. The Settings.h is #includeed in main.cpp and AmalgamService.cpp

Upvotes: 1

Views: 425

Answers (1)

Nikos C.
Nikos C.

Reputation: 51832

You seem to be including Settings.cpp in another file. Do not include .cpp files. This results in duplicate definitions. This also means that #pragma once in .cpp files is useless.

You need to keep in mind that #include is just a glorified copy&paste tool. When you #include a file, that file is literally being copy&pasted into the spot of the #include statement. So including a .cpp file means you will get multiple definitions of everything defined in that .cpp file.

Furthermore, you don't have to use extern when declaring functions. Functions are extern by default, unless you say otherwise.

Variables are extern by default too, however you need to use extern as a way to declare them without defining them:

extern int var; // declaration
int var; // definition

Functions don't need that, because you can declare them by omitting their body:

void func(); // declaration
void func() { } // definition

You are allowed to declare things multiple times, which is why you can #include header files (like .h, .hpp) in multiple files. But you are not allowed to define things multiple times, which is why you can't #include non-header source files.

Upvotes: 1

Related Questions