C++ global namespace members already defined error - c++

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

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.

Related

Already defined in .obj even when using extern and #ifdef

I have three files like this:
head.h
#ifndef HEAD_
#define HEAD_
extern int f();
#endif
mycpp.cpp
#include "head.h"
int f() {
return 5;
}
myMain.cpp
#include <iostream>
#include "head.h"
#include "mycpp.cpp"
int main()
{
std::cout << f() << std::endl;
system("Pause");
return 0;
}
Running this code produces a link error:
LNK2005 "int __cdecl f(void)" (?f##YAHXZ) already defined in mycpp.obj
If I add inline to the function f in mycpp.cpp the error goes away.
My question is how to get rid of this error without using the inline function?
P.S. This is an assignment and I can only modify the mycpp.cpp file. So the #include "mycpp.cpp" has to be there.
I know it is a bad idea to include cpp files, but I cannot change the myMain file. It is given this way. And I am not supposed to use inline.
The general rule is: never #include a .cpp file. Only header files should be included.
Besides that, extern in a function declaration is redundant here. On a variable declaration, extern marks the statement as a declaration rather than a definition. But on function declarations this isn’t necessary, and the function has external linkage anyway.

Linker error when including header in files other than main.cpp

I'm trying to add some utility functions and global variables to my code in such a way that I can be able to use them in every class I want in my project. I would like to use a .hpp file for the definitions end a .cpp file for the implementation.
This is a summary of these two files:
// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp
namespace utils {
int global_variable1;
int global_variable2;
void utility_function1(...);
void utility_function2(...);
void utility_function3(...);
}
#endif /* utilities_hpp */
and the implementation:
// This is Utilities.cpp
#include "Utilities.hpp"
namespace utils {
void utility_function1(...) {
// Some code
}
void utility_function2(...) {
// Some code
}
void utility_function3(...) {
// Some code
}
}
Other than my main.cpp file I have two other classes. My main.cpp file includes Class1.hpp header that includes Class2.hpp header.
Now I thought that I could put another #include "Utilities.hpp" in Class1.hpp or Class2.hpp without any problems since I've used the guards in that header. The thing is that when I try to do that the linker throws me this error: Apple Mach-O Linker (ld) Error Group - clang: error: linker command failed with exit code 1 (use -v to see invocation) and I can't understand why or what to do to solve it.
I'm using Xcode 8.3 on a macOS Sierra 10.12.4.
I hope I was able to explain my problem, thank you all very much in advance.
You've violated the One Definition Rule. global_variable1 and global_variable2 should be declared extern in your header and defined in exactly one translation unit (probably Utilities.cpp).
You've defined global variables in a header that gets included in multiple translation units, so there's a utils::global_variable1 defined in main.cpp, and one in Utilities.cpp. When it comes to link time, the linker has no way to know which global_variable1 to use, so it throws an error.
To fix it, add the extern keyword to your declarations and add a definition in "Utilities.cpp":
Utilities.hpp:
// This is Utilities.hpp
#ifndef utilities_hpp
#define utilities_hpp
namespace utils {
extern int global_variable1;
//^^^^^^ <-----HERE
extern int global_variable2;
//^^^^^^ <-----HERE
void utility_function1(...);
void utility_function2(...);
void utility_function3(...);
}
#endif /* utilities_hpp */
Utilities.cpp:
// This is Utilities.cpp
#include "Utilities.hpp"
namespace utils {
int global_variable1; //<---- Definitions added
int global_variable2;
void utility_function1(...) {
// Some code
}
void utility_function2(...) {
// Some code
}
void utility_function3(...) {
// Some code
}
}
You're missing the extern keyword on your global variables in your header. As a result, you're defining them, which results in multiple definitions when you include the header in two different source modules.
Once you add the extern in the header file (extern int global_variable1;), you'll need to add the definition in your .cpp file where you also define your functions.

Why is my global variable causing problems?

I've been reading about global variables for an hour now and I can't get mine to work. I have two vectors of custom classes, Airport and Flight, which are defined in their respective header files. Then I declare the extern vectors in the Globals.h header which is included in main.cpp. If I leave the code as is, I get a "unresolved external symbol" error for both of the vectors:
error LNK2001: unresolved external symbol "class std::vector<class Airport,class std::allocator<class Airport> > airports" (?airports##3V?$vector#VAirport##V?$allocator#VAirport###std###std##A)
error LNK2001: unresolved external symbol "class std::vector<class Flight,class std::allocator<class Flight> > flights" (?flights##3V?$vector#VFlight##V?$allocator#VFlight###std###std##A)
If, instead, I forward declare (like I've been lead to believe is how it should be done) by putting
vector<Airport> airports;
vector<Flight> flights;
in front of main(), then I get these errors:
error C2371: 'airports' : redefinition; different basic types
error C2371: 'flights' : redefinition; different basic types
There's also errors given about allocators in vectors, and how one vector is not equal to the other vector. However, I cannot create a vector by typing vector> airport, which is what is suggested. This is mirrored by vector.
The code in my project is below. Any help would be appreciated.
main.cpp (simplified):
#include "stdafx.h"
#include "Globals.h"
using namespace std;
int main(){
airports = readInAirports();//returns a vector<Airport>
flights = readInFlights();//returns a vector<Flight>
}
Airport.h: (Flight.h is similar)
#ifndef AIRPORT_H
#define AIRPORT_H
#include <vector>
#include <string>
using namespace std;
class Airport{
public:
Airport(string c, string n, int dt, int cc)
:code(c), name(n),
departureTax(dt),connectionTime(cc)
{}
string toLine();
string getCode();
string getName();
int getDepTax();
int getConnTime();
private:
string code, name;
int departureTax, connectionTime;
};
#endif
Globals.h:
#ifndef GLOBALS_H
#define GLOBALS_H
#include <vector>
#include <string>
#include <math.h>
#include "Airport.h"
#include "Flight.h"
extern vector<Airport> airports;
extern vector<Flight> flights;
#endif
extern vector<Airport> airports;
This is a declaration of airports. It says "Somewhere in the program is a global variable called airports of type vector<Airport>".
vector<Airport> airports;
This is a definition of airports. It creates a global variable called airports of type vector<Airport>. You cannot have two global variables with the same name, even if they are in different files.
You should know that #include effectively copy-pastes the whole contents of the included file into this file. So if you put a definition in a header file, and include that header file in two different source files, then you have two definitions.
The solution is to put the declarations in the header file (with extern) and the definitions in one source file.
Because you have't defined them. You only declared them (extern only declares).
You need to add the definitions for both airports and flights in a .cpp file, like so:
vector<Airport> airports;
vector<Flight> flights;
Furthermore, vector<Airport> airports; is not a forward declaration, it's a definition. To forward declare variables you need to use the extern keyword.

Why linker is giving error for global variable in header file

I have declared a global variable in header.h and included that header in source.cpp and main.cpp but linker is giving error
Source.obj : error LNK2005: "int globalVariable" (?globalVariable##3HA) already defined in Main.obj
GlobalVariableAndLinkageIssue.exe fatal error LNK1169: one or more multiply defined symbols found
header.h
int globalVariable;
source.cpp
#include "header.h"
main.cpp
#include"header.h"
void main() {}
Move the declaration to a .cpp file. You can use a declaration in a header file by using:
extern int globalVariable; // declaration in header - can have as many as you need
But the .cpp file should have the definition:
int globalVariable; // definition in .cpp - only need one across all your files
C and C++ use textual pre-processor to include headers, this is basically a text insertion, not a smart module system as in some languages. By including it as you were, you are creating multiple definitions, one per .cpp file.
As a matter of good practice, you need to get used to using include guards to protect against multiple nested includes (though it would not solve your current issue). If using Visual C++, you can use #pragma once or to use a portable solution wrap your header code in:
#ifndef _INCLUDE_FOO_H_
#endif
To create a global variable, you should do the following. Note that in the header, we mark the variable as extern, and we actually create the object in a cpp file.
header.h
extern int globalVariable;
header.cpp
#include "header.h"
int globalVariable;
main.cpp
#include "header.h"
int main() {}
Put global variable in some .c or .cpp file, so that it can be defined only once and refer in header file using extern
for example,
header.h
extern int globalVariable;
header.cpp
int globalVariable = 0;
source.cpp
#include "header.h"
main.cpp
#include"header.h"
int main() {
return 0;
}
Because BOTH sources #include your header, and thus it is DEFINED twice.
In such situation,it is common to use some #define as follows:
//header.h
#ifdef DEFINE_VARS
#define DEFINE_OR_DECLARE
#else
#define DEFINE_OR_DECLARE extern
#endif
DEFINE_OR_DECLARE int globalVariable;
//main.cpp
#define DEFINE_VARS
#include "header.h"
...
//header.cpp
#include "header.h"
...

creating global variables causes linker error

I have an MFC application AVT_testapp, and in the header file (AVT_testappDlg.h) I am trying to create a variable outside of all functions, classes, etc. in order to make it global. Whenever I try to do this though (say I try int x = 7), I get the error:
1>AVT_testappDlg.obj : error LNK2005: "int x" (?x##3HA) already defined in
AVT_testapp.obj
1>..\..\bin\x64\Debug\AVT_testapp.exe : fatal error LNK1169: one or more
multiply defined symbols found
Everything I have found on google says "just add header guards". AVT_testappDlg has 6 #include's, and each of them has header guards.
What else could be causing these errors when creating global variables?
EDIT: Here is the beginning of my header file,
#pragma once
#include "../../src/CoreUtils/nierr.h"
#include "..\..\src\CoreUtils\StringHelpers.h" //includes windows.h
#include "afxwin.h"
#include "afxcmn.h"
#include "IFrameObserver.h"
#include "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\GdiPlusHeaders.h"
//#include <fstream>
//#include <windows.h>
int x = 7;
using namespace AVT::VmbAPI;
//////////////////////////////////////////////////////////////////////////
////////// MyObserver class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class MyObserver : public IFrameObserver
{
private:
MyObserver( MyObserver& );
MyObserver& operator=( const MyObserver& );
public:
VmbUchar_t* imageData;
//...
//...
//...
//...
//that's the end of the relevant stuff
You cannot define variables at namespace level in a header. In general it is best not to have global variables, but if you need to you should provide only a declaration in the header and the definition in a single .cpp:
//header
extern int i;
//cpp
int i;
The problem with your code is not related to header guards. Header guards ensure that a header is parsed only once in each translation unit. Lack of header guards causes compiler errors, where the compiler sees, say for example a class, defined multiple times in the same translation unit after preprocessing. In your case the error is a linker error LNK2005, and it means that the same symbol was defined in multiple translation units (in your case in each translation unit that includes the header with the definition).
If the global variable is not const(*), you cannot put it in a header file and include it in multiple translation units (i.e. .cpp files). Otherwise, you will end up with multiple definitions of the same symbol in your program, violating the ODR (One Definition Rule, see Paragraph 3.2 of the C++11 Standard), and the linker will complain about that.
You should use the extern modifier in your shared header to provide only a declaration of your variable:
extern int var;
Then, in one single .cpp file, you can provide a definition for it:
int var;
(*) const global variables have internal linkage by default, so each translation unit will end up having a private copy of it and no multiple definition will occur.
if you insist on having a global variable at least put it in a namespace to avoid collisions with other modules
namespace globals
{
extern int x;
}
then in the .cpp file define it.
int globals::x = 0;
it also makes it more clear that it is a global variable.