I am working on a library that I'm using in my other projects and I have the following header file:
#pragma once
#include <iostream>
#include <map>
#include "my_library/core/Structures.h"
namespace My_Library
{
namespace NodeReaders
{
namespace HumanReadable
{
char charBuffer[256];
unsigned int uintBuffer;
unsigned long long microsecondBuffer;
unsigned int getNextUInt(std::istream & is)
{
/// Implementation
}
unsigned long getNextMicroseconds(std::istream & is)
{
/// Implementation
}
...
}; // namespace HumanReadable
}; // namespace NodeReaders
}; // namespace My_Library
I've tried to include it in a couple of different source files, but whenever I do, I get an error that there is a duplicate symbol for each of the used functions defined here. Why am I getting a duplicate symbol error? Isn't #pragma once supposed to make it so that that doesn't happen?
Edit: Snippit of error message:
duplicate symbol __ZN8My_Library11NodeReaders13HumanReadable10uintBufferE in:
obj/project/Debug/ParseDriver.o
obj/project/Debug/ParseService.o
#pragma once makes sure the header file is only included once in each translation unit it's included in. So if you include it in more than one cpp file, you will get multiple implementations.
Declare your functions inline e.g. :
inline unsigned int getNextUInt(std::istream &is)
{
...
}
Or, put the function implementations in a cpp file.
The variables have to be defined in a cpp file. In the header file, you will have this:
extern unsigned int uintBuffer;
and in the cpp file you have this:
unsigned int uintBuffer;
All of this becomes easier when you use classes instead of global variables and functions.
Related
I have created header file abc.hpp which contains a namespace of multiple functions.
When I use single source file which includes the header and call the function defined in namespace it works well, but when I call the same function in project where I have to include this header in multiple places, compilation gives me multiple definition error.
My other files are created as library and get executed.
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
namespace abc {
void sendtext(const char* msg)
{
create_context(mycontext);
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn)
{
create_context(mycontext);
send_context(create_context,msg, errn)
}
};
#endif
test.cpp:
#include"abc.hpp"
int main()
{
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
You can treat header files as if they are copy-pasted into your implementation files. So by putting function definitions into your headers, those definitions appear in multiple translation units (roughly, compiler .cpp files). This is not allowed - how is the compiler supposed to tell between them if they end up different?
Usually you would have a .h/.cpp pair, with function declarations going in the .h, and function definitions going in the .cpp. This way the definition only appears once in your whole program.
I can split your code like this:
abc.hpp:
#ifndef __ABC_HPP__
#define __ABC_HPP__
// function **declarations**
namespace abc{
void sendtext(const char* msg);
void sendtextwitherrno(const char* msg, int errn);
}
#endif
abc.cpp:
#include "abc.hpp"
#include "context.hpp" // I guess this might be where create_context and send_context come from
// function **definitions**
namespace abc{
void sendtext(const char* msg){
create_context(mycontext); // not sure where mycontext is supposed to live?
send_context(create_context,msg)
}
void sendtextwitherrno(const char* msg, int errn){
create_context(mycontext);
send_context(create_context,msg, errn);
}
}
test.cpp:
#include "abc.hpp"
int main(){
abc::sendtext("hello world");
abc::sendtextwitherrno("hello error no",140);
return 0;
}
Another way is to mark the functions as inline - this tells the compiler you are deliberately repeating the function definition all over the place, and you'd better be sure the definition is always identical. How sure are you? Are there different macros or different compiler flags in place in different places the function is used?
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.
So, I am working on a project and decided to split the code into multiple files as it was getting too big. However, a got a compilation error. I managed to recreate the error in this simple case:
//main.cpp
#include<iostream>
#include "classa.h"
using namespace std;
int main()
{
return 0;
}
The main does nothing it just includes classa.h
//classa.h
#ifndef CLASSA_H_INCLUDED
#define CLASSA_H_INCLUDED
#include<vector>
using namespace std;
vector<int> primes= {1,2,3,5,7,11,13,17,19};
class classa
{
private:
int a;
public:
int getA();
void setA(int newA);
};
#endif //CLASSA_H_INCLUDED
The class isn't even necessary for the error to occur. However, I wanted to have something in classa.cpp
//classa.cpp
#include "classa.h"
using namespace std;
int classa::getA()
{
return a;
}
void classa::setA(int newA)
{
a=newA;
}
It gives me the following error:
obj\Debug\sources\main.o:main.cpp:(.bss+0x0): multiple definition of `primes'
obj\Debug\sources\classa.o:classa.cpp:(.bss+0x0): first defined here
The problem is that unlike here in my project I cannot use some sort of constant or a define for the global variables as they are things that can be modified by different classes.
Make primes an extern variable, and declare it in your classa.h header, but only defined it once in classa.cpp.
Currently, as your compiler told you, primes exists twice, in main.cpp and in classa.cpp. Keep in mind, #include is merely text substitution.
classa.h:
extern std::vector<int> const primes;
classa.cpp:
std::vector<int> const primes = {1,2,3,5,7,11,13,17,19};
Read more about storage class specifiers here.
If you have .cpp file in overall - then it makes sense to split into
Into .h file:
extern std::vector<int> primes;
Into .cpp file:
using namespace std;
vector<int> const primes = {1,2,3,5,7,11,13,17,19};
"using namespace std" might cause conflicts between 3rd party libraries, but this occurs very rarely - I prefer to use "using namespace std" whenever possible. But if there are conflicts - then you might want to localized "using namespace std" into your own .cpp file. (Where you control what #include's that file has).
But sometimes you might not have .cpp file at all (e.g. only local inline functions or template classes) - then you can initialize vector like this:
__declspec(selectany) std::vector<int> primes = {1,2,3,5,7,11,13,17,19};
This will instruct linker to pick up only one copy (some of them), and discard everything else. This does not play well if you want to #ifdef some of initialization, but this is not normal use case anyway.
I prefer not to use const ever, because it's always pain in neck to get const right after 2-3 level conversions. I write in function comments what is input / what is output and what should not be modified. (Because that one can change over iterations)
I had a .h file with some class code - overlay.h
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
Now I moved the struct to another new file called member.h
and included this file so my class overlay_server could use it.
Now when I build the program I get the error.
What changes should I make to make this work?
I read about header guards on SO, but couldnt really understand how to implement it here to solve the problem.
----edit----
member.h
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
run.cpp
#include<overlay_server.h>
#include<overlay_client.h>
int main(){
overlay_server overlay_server_(8002);
boost::thread thread_(boost::bind(&overlay_server::member_list_server, overlay_server_));
overlay_client overlay_client_("127.0.0.1",8002);
overlay_client_.member_list_client();
thread_.join();
}
I dont have redefinition of struct anywhere.
I have another class called overlay_client it also uses struct member.
In my main function, i create objects of both overlay_server and overlay_client.
Now my program runs only if member.h is included in overlay_server.h (though code in both overlay_server and overly_client requires it)
if its included in both then i get the redefinition error
why?
----edit----
this code in my member.h solves the issue
Compile error "'struct' type redefinition" although it's the first definition for it
You can also use a pragma and get the same effect. At the top of all your header files, write:
#pragma once
rest of the header
.
.
.
And the way to use include guards is to surround all the contents in a header file with an include guard, which looks like this:
// At the very top
#if !defined(SOME_SYMBOL)
#define SOME_SYMBOL
rest of the header
.
.
.
// At the very bottom
#endif // SOME_SYMBOL
Now, choosing a sensible name instead of SOME_SYMBOL is very important. Most programmers make a guard name based on the file name (and path and project name and company/individual name.) For example, for a header named "some_header.h" (or "SomeHeader.h") located in "[project root]/include/myproject", you would name the guard name to be __INCLUDE__MY_PROJECT__SOME_HEADER_H__. But this is just a suggestion; any unique symbol will do.
You can also combine the pragma and the include guards (because the pragma method can improve the compile time in very large projects, but not all compilers support it.) If you want them both, you'd write:
#pragma once
#if !defined(__INCLUDE__MY_PROJECT__SOME_HEADER_H__)
#define __INCLUDE__MY_PROJECT__SOME_HEADER_H__
rest of the header
.
.
.
#endif // __INCLUDE__MY_PROJECT__SOME_HEADER_H__
This has no adverse effects (to my knowledge,) only the potential to prevent build errors and to make your builds faster (on large projects.) But note that the meanings of include guards and #pragma once are not exactly the same. In very very rare cases, you would need to use one or the other, or neither.
This is whats happening.
you have
member.h
included in overlay_server.h and in overlay_client.h
now when you include these two in main.cpp
it is like you are doing this in main.cpp(actually preprocessor expands like below)
#include"member.h"
#include"member.h"
so it typically will be like this after complete expansion
struct member{...};
struct member{...}; //redifinition!!
so the compiler parses it as being two definition of struct member(because it will visit member.h twice and read the def of member struct).
what to do to avoid this
in member.h add this
#ifndef MEMBER_DECL //initially not defined
#define MEMBER_DECL //include guard(now first time you enter this MEMBER_DECL will get defined. so second time compiler comes here it skips this.)
struct member
{
//rest here
};
#endif
now in main you will have this
#include"member.h" //when this happens MEMBER_DECL is defined
so
//#include"member.h" member will not be expanded again hence resolving your redfinition
If overlay.h contains a struct member definition and member.h also has a struct member definition, you cant include member.h from overlay.h. Here is how include guards work though:
#include<iostream>
#include<boost/thread.hpp>
#include<vector>
#include<boost/asio.hpp>
#include <string>
#include <boost/serialization/vector.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <sstream>
#include <boost/tuple/tuple.hpp>
#include<member.h>
#ifndef _H__MEMBER_
#define _H__MEMBER_
using boost::asio::ip::tcp;
class overlay_server{...};
struct member{
std::string ip_address;
short int port;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & ip_address;
ar & port;
}
};
#endif
Notice the #ifndef _H__MEMBER_ and #define _H__MEMBER_ and #endif. With the include guards, it makes sure your header is only included once because after the first time it's included H_MEMBER_ will be already defined so it will skip the definition. Your naming convention can be different but usually I do something along the lines of _H__<HEADER NAME>_ as my defines.
I'm having a problem compiling the following code with avr-g++ (C++ compiler for AVR micro-controllers).
#ifndef SPI_H_
#define SPI_H_
#include "../LIBcpp.hpp"
namespace uC
{
namespace SPI
{
class Device
{
private:
SPI* m_SPI;
uC::IO::Pin* m_CSPin;
ChipSelectPolarity m_CSPolarity;
public:
Device(SPI& _SPI, uC::IO::Pin& _CSPin, ChipSelectPolarity _CSPolarity);
void Select();
void DeSelect();
void WriteByte(uint8_t _Data);
uint8_t WriteReadByte(uint8_t _Data);
void WriteBytes(uint8_t _Data[], uint8_t _DataLength);
void WriteReadBytes(uint8_t _Data[], uint8_t _ReadBuffer[], uint8_t _DataLength);
};
}
}
#endif /* SPI_H_ */
Note that I have defined several enumerations and classes within this file that are used in this class but have not been included to prevent the code from being too long.
I receive the errors
'IO' in namespace 'uC' does not name a type
'uC::IO' has not been declared
expected ',' or '...' before '&' token
In my project, I have several files that represent specific modules of the project that I am working on. These files are in a sub-directory named Modules. The header file LIBcpp.hpp is in the directory above that. It includes the all of the header files within the Modules sub-directory.
The class Pin is defined within the namespace IO, which is within the namespace uC. This class is defined in a header file named IO.hpp, which is included by LIBcpp.hpp.
What I have tried:
Including the IO.hpp header file in the SPI.hpp header file - resulting in the same errors
I am at a loss as to how to solve this error. If more code or information is required to solve this problem, I will provide it.
Thanks!
This is IO.hpp, as requested:
#ifndef IO_H_
#define IO_H_
#include "../LIBcpp.hpp"
namespace uC
{
namespace IO
{
class Port
{
//Contents removed
};
class Pin
{
//Contents removed
};
}
}
#endif /* IO_H_ */
The class "Pin" is defined within the namespace "IO", which is within
the namespace "uC". This class is defined in a header file named
"IO.hpp", which is included by "LIBcpp.hpp".
But IO.hpp includes LIBcpp.hpp. You have circular inclusions- this is extremely bad. You must alter your header structure so that there are no circular inclusions.