I have used include guards many times before, but never really understood how or why they work.
Why doesn't the following work?
#ifndef CAMERA_CLASS_HPP
#define CAMERA_CLASS_HPP
class camera_class
{
....
};
camera_class glcam = camera_class();
#endif // CAMERA_CLASS_HPP
The error is this: (You can probably guess what it's going to be from the title of this question!)
-------------- Build: Debug in System ---------------
Linking console executable: bin/Debug/System
/usr/bin/ld: error: obj/Debug/main.o: multiple definition of 'glcam'
/usr/bin/ld: obj/Debug/camera_class.o: previous definition here
/usr/bin/ld: error: obj/Debug/main.glfunc.o: multiple definition of 'glcam'
/usr/bin/ld: obj/Debug/camera_class.o: previous definition here
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings
Also, could someone please explain to me why a header guard works?
The header guard will prevent multiple inclusions in a single translation unit. The header can (and is) being included in multiple translation units:
// a.cpp:
#include "camera.hpp"
// b.cpp
#include "camera.hpp"
This will produce a a.obj and a b.obj, each containing a definition for glcam. When linked together to produce the final binary you get the multiple definition error.
You need to declare glcam in the header and define it exactly once in a .cpp file:
// camera.hpp
...
extern camera_class glcam;
// camera.cpp
#include "camera.hpp"
camera_class glcam;
Root Cause:
The header guard prevents inclusion of the same header multiple times in the same translation unit but not across different translation units. When you include the same header file in multiple translation units then,
A copy of glcam is indeed being created in every translation unit where you include the header.
C++ standard mandates that each symbol can be defined only once(One Definition Rule) and hence the linker issues you the error.
Solution:
Do not create glcam in the header file. Instead it should be created in such a way that it gets defined only once. The correct way to do this is by using the keyword extern.
It looks like you want to create a single glcam object that can be used in multiple places. I would do that by exposing a free function to return a static instance. This is similar to using extern, but I find it to be a little more explicit in its intent.
#ifndef CAMERA_CLASS_HPP
#define CAMERA_CLASS_HPP
class camera_class
{
....
};
camera_class& get_camera();
#endif // CAMERA_CLASS_HPP
// in the CPP
camera_class& get_camera()
{
static camera_class the_camera;
return the_camera;
}
This gives you the ability to use a single camera_class instance without relying on extern, but at the same time doesn't force you to use it as a singleton, as other areas of the code are free to create their own private instances as well.
This could be implemented as it is (a free-function) or as a static member function of the camera_class. I chose the former, based on some excellent advice from Scott Meyers:
If you're writing a function that can be implemented as either a
member or as a non-friend non-member, you should prefer to implement
it as a non-member function.
Source: http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
Since you are including this file from several files, you are breaking the One Definition Rule:
In the entire program, an object or non-inline function cannot have
more than one definition
You should put the glcam definition in a source file, rather than in a header file, or instead declare it as extern, and provide a definition in some source file.
The include guard prevents multiple instances of the text in your header from appearing in one compilation unit (ie a single .cpp you're building which gets built into a .o)
It doesn't prevent multiple instances of that text from appearing in multiple compilation units.
So at link time, each compilation unit that includes this header has a
camera_class glcam = camera_class();
As a symbol. C++ can't decide when referring to "glcam" which single global definition you mean. The one from main.o or the one from camera_class.o?
It's working just fine, you're only getting one definition in each of your source files.
The problem is that you have multiple source files and the linker is finding multiple definitions.
In the header file you should put:
extern camera_class glcam;
And then in one and only one source file put what you used to have in the header:
camera_class glcam = camera_class();
At this point you'll need to be aware of initialization order problems. Don't try to use glcam from any static objects.
Related
I have a header file which begins with
#if !defined(__GLOBAL_H)
#define __GLOBAL_H
then some code followed by
#endif
The code contains only function declarations, some include of other header files and the a few template functions. However, the problem occurs when I add one single line of code. I get linker error that the function I added has already been defined in an object file. I'm using Visual Studio 2012 Premium as compiler. I have tried to remove any existing function from the header file, and that also goes through the compiler. On the other hand, if I add any new line that may be new to the compiler, it refuses to compile saying it has already been defined. Does anyone have any clue what might be wrong or can I have stumbled upon an error inside the compiler itself? (which I highly doubt)
Edit:
The solution was to declare the function the the header file, but to define it in the CPP file. But the real issue was that when I include a header file for returning an object of the type declared in the header file, it does not compile. It many of the errors "Missing ; in front of *" which was types declared in other header files.
Although you haven't shown use any code or error messages, I'm guessing that there are function definitions (including the code for the function body), not just declarations, in the header.
These must either be declared inline, which allows them to be defined in more than one translation unit; or moved into a single source file, leaving just the declaration in the header, so they are only defined on one translation unit.
The "One Definition Rule" says that (unless they are inline) functions may only have one definition in the program.
Also, your include guard shouldn't begin with an underscore, nor contain a double underscore; names like that are reserved.
Adding non-inlined function definitions to header files is generally bad. The compiler will generate code for the function in every file it is included in resulting in the redefintion error you are encountering. Instead you should declare the function in the header and place the definition in a source file (.cpp).
Global.h
#if !defined(__GLOBAL_H)
#define __GLOBAL_H
void somefunction(); // <-- declaring the function.
#endif
SomeSource.cpp
#include "Global.h"
// Here is where define the function
void somefunction()
{
}
I'm new to using header files and such, last semester we did everything in one giant(horrible :p) file ...
Am I doing something I'm not supposed to? Attempting to run the program results in the following:
1> LINK : ~~~\CSC 161\Accounting Assignment\Debug\Accounting Assignment.exe not found or not built by the last incremental link; performing full link
1>driver.obj : error LNK2005: "class std::basic_ifstream<char,struct std::char_traits<char> > welcomeFile" (?welcomeFile##3V?$basic_ifstream#DU?$char_traits#D#std###std##A) already defined in statistics.obj
1>~~~~\CSC 161\Accounting Assignment\Debug\Accounting Assignment.exe : fatal error LNK1169: one or more multiply defined symbols found
1>
statistics.h:
#ifndef _STATISTICS_INTERFACE_
#define _STATISTICS_INTERFACE_
...
#include<fstream>
using namespace std;
ifstream welcomeFile; //if I comment this out, it compiles
class Stats
{
...blah...
};
void welcome();
void pause();
void printFile(ifstream &inFile);
#endif
statistics.cpp:
#include "statistics.h"
...working functions...
void welcome()
{
system("CLS");
welcomeFile.open("about.txt");
printFile(welcomeFile);
welcomeFile.close();
pause();
}
The errors look like something is trying to be defined twice, but I thought #ifndef was supposed to set it so it only defined things if they weren't already? This is the only place where I declared welcomeFile ...
Because you defined the object in the header file and violated one definition rule.
Never define objects in header file!
Header guards prevent the contents of the header to be included multiple times in the same translation unit during preprocessing. They do not prevent the contents to be included in different translation units. When you include this header file in different translation units, each of these units will have a definition of this object.
The compiler compiles each translation unit separately to produce a separate object file(.o), each of those .o files will have an copy of this object definition. When the linker tries to link to the object/symbol name at time of generating the .exe it finds multiple definitions of the same object/symbol, thereby causing confusion as to which one to link to. To avoid this problem the standard defines a rule known as the One defintion rule(ODR), which forbids multiple definitions of the same entity.
As you see including the object definition in the header file and including that header file in multiple translation units violates the ODR.
If you want to use a global object, You need to declare it as extern and define it in one and only one source file.
Good Read:
error LNK2005, already defined?
You should put that definition in a .cpp file. Otherwise, every file that includes this .h file will have a definition of this variable, which ultimately clash during linking.
p.s. putting using namespace std; in your header, is considered bad.
I don't wish to create a wall of code so if you need any code just ask and i will post. I am getting multiple definition errors and i have no idea why. i believe the error is occurring because i am attempting to declare a variable in one header file(as well as create an object for it in the same header) and then use it among 4 different files.and for each file i use the header in i get multiple definition, with the small amount of info i have given you any ideas as to why this is occurring?
please ask if more information is required to solve the question.
I am using Code::Blocks ide mingW compiler and programming on Windows 7
EDIT
Thanks you all for your extremely fast help you have solved my problem :D
Don't declare it in a header file (although technically, I mean don't define it there).
In your header file you should have:
extern int variableIWantOneCopyOfOnly;
and then, in a single C source file that you will link in, put:
int variableIWantOneCopyOfOnly;
The former will let all your source files know about the existence of the variable but without allocating space for it. The single translation unit containing the second line will allocate the space for it and the linker will fix up all the references to it.
Include guards won't help with multiple definitions since they only stop the inclusion within a single translation unit.
By that I mean, if you have the following files:
xyz.h: xyz1.c: xyz2.c:
#ifnef XYZ #include "xyz.h" #include "xyz.h"
#define XYZ
int a;
#endif
and you execute a command like:
gcc xyz1.c xyz2.c
then they will both get the own copy of a, not share a copy, because the scope of the include guard is the translation unit, not the executable created by the linker.
Have you used include guards in your header? Generally, you want to structure your headers something like this:
#ifndef _HEADER_FILE_H
#define _HEADER_FILE_H
// actual definitions
#endif
There's also #pragma once, but that is not standard.
"as well as create an object for it in the same header"
If you define things in your headers, and then try to link objects from multiple translation units including that header, you'll get multiple definition errors.
If the header's called say x.h, create an x.cc (or x.c++, x.cpp or whatever you normally do) that includes the header. Move the definition of the object in there. Compile it and link it with the other objects in your application.
the multiple definition error means you are declaring many times the same variable. Regarding what you are doing, this occurs because you are including 4 times the same file (so you are declaring 4 times your variables.
Add the preprocessor
#ifndef _HEADERFILE_H
#define _HEADERFILE_H
// Your declarations
#endif
or if you are using Visual studio just add this on the first line of the file:
#pragma once
You should move the actual definition into a c++ (.cc .cpp whatever) file and only leave the declaration within the header. Also you will need to prefix the declaration with 'extern'.
This function is global and is defined in the header file (temporarily I want to keep it there).
The header file also constitutes a particular class which has inline functions and one of those functions call this global function.
The source file doesn't contain any occurrences of the global function in question.
Any hints on cause of the error?
I can post the code if anyone is interested.
mainwindow.o: In function `tileForCoordinate(double, double, int)':
mainwindow.cpp:(.text+0x310): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
moc_mainwindow.o: In function `qHash(QPoint const&)':
moc_mainwindow.cpp:(.text+0x0): multiple definition of `qHash(QPoint const&)'
main.o:main.cpp:(.text+0x0): first defined here
moc_mainwindow.o: In function `tileForCoordinate(double, double, int)':
moc_mainwindow.cpp:(.text+0x150): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
collect2: ld returned 1 exit status
make: *** [SimpleRouting] Error 1
mark it as inline:
inline void globalfunc() {
}
although doing so means that it will no longer strictly be global - you will get a copy in each translation unit that uses the header, but the linker won't object to this.
If you put a function in the header it will be generated for each c/cpp file that includes that header leading to duplicates. Making it inline will help.
Edit, explanation
Header guards as the #ifndef, #define ... #endif construction is often called only prevent double and recursive inclusion in a single cpp file. This is relevant in the case where a source file includes headers A and B and B also includes A. Recursive inclusion would happen if A also included B.
Your problem arises because you have multiple .cpp files. During compilation of one cpp the compiler doesn't know about the existence of the other cpp files.
Notice that #include, #ifdef and friends are preprocessor directives. Preprocessing happens on source files before compilation (thought it is often regarded and done as part of the compilation process). The preprocessor basically is a text processor. For instance an #include is textually replaced with the contents of the header file. Contents of #ifdefs that evaluate to false are removed from the code. The actual compiler gets one single big file consisting of the cpp and all referenced include files which it translates into an object file.
You have 2 options:
Mark it as inline, as explained by nbt, or as static.
inline will take the implementation of the global function from the source and copy it into wherever the function is called.
inline void global_func ()
{
...
}
static will tell the linker to not copy the code into the new object file but rather only reference it in the original.
static void global_func ()
{
...
}
For a global function defined in a header file, declaring it within an un-named namespace should/will also work. According to C++ How to Program by Deitel, in C++ an unnamed namespace is preferable to static.
So you could do this:
// \file GlobalFunctions.h
namespace // an un-named namespace
{
void GlobalFunctionOne() {...implementation...}
} // end un named namespace
#ifndef SOMESTRING
#define SOMESTRING
... header code
#endif
The code of the header will only be included the first time.
I have a template matrix class class defined in a header called "Matrix.h".
Certain matrices are used repeatedly in my program. I thought that I would define these in the "Matrix.h" header file, like so:
const Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
When I do this g++ complains that I redefined the constant in question. This happens because I include Matrix.h in two different source files. When the object files for these are compiled, both end up with a definition of the matrix above, causing the error message.
My question is how do I avoid this situation? I want a constant that is accessible to more than one file, but I don't know where to put it.
You avoid it by:
Declaring it extern in the header. A symbol can be declared any number of times.
Defining it in the implementation, only once.
If you don't want to split it between a header and implementation file,
Declare your constant static (or declare it in anonymous namespace) to make definition private. Linker will not complain, but it will result in multiple private copies across compilation units.
static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
Make an inline function that returns the constant. Inline function definitions produce "weak" symbols in object file, so linker will eliminate duplicates and pick one.
inline const Matrix<GLfloat>&
GET_B_SPLINE_TO_BEZIER_MATRIX() {
const static Matrix<GLfloat> B_SPLINE_TO_BEZIER_MATRIX(4, 4, values);
return B_SPLINE_TO_BEZIER_MATRIX;
}
just write your header file like this
#ifndef HEADER_FILE_NAME_H
#define HEADER_FILE_NAME_H
// your header file code
#endif
this will make sure that it won't get declared multiple times
Wrap header files (.h) in preprocessor conditionals to prevent them from being included in the compiler's symbol table twice:
#ifndef HEADER_NAME
#define HEADER_NAME
// code...
#endif//HEADER_NAME
HEADER_NAME can really be anything, but it's best to make sure that it's something related to the file to prevent more collisions, as this is just defining an empty preprocessor macro (which also ends up in the symbol table).