At: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/
Under Header guards, there are those code snippets:
add.h:
#include "mymath.h"
int add(int x, int y);
subtract.h:
#include "mymath.h"
int subtract(int x, int y);
main.cpp:
#include "add.h"
#include "subtract.h"
How can I avoid #include "mymath.h" from appearing twice in main.cpp?
Thanks.
The lines right below that example explain it. Your mymath.h file should look like this:
#ifndef MYMATH_H
#define MYMATH_H
// your declarations here
#endif
Every header file should follow this basic format. This allows a header file to be included by any file that needs it (both header and source files), but the actual declarations will only be included at most once in each source file.
use #pragma once if you using MS VC++ or the standard way
inside mymath.h
#ifndef MYMATH_H
#define MYMATH_H
[code here]
#endif // MYMATH_H
That's ok if they included twice if all the headers files have header guards. The second and all subsequent inclusions would just add empty lines and there won't be any code duplication. Just make sure that mymath.h has header guards as well.
You should put your header guards in any header, also in mymath.h.
Related
How can I exclude certain #include statements in my .h file depending on which .cpp is including the .h file?
Example:
main.cpp file
<tell the header.h file that main.cpp is including it>
#include "header.h"
other.cpp file
<tell the header.h file that other.cpp is including it>
#include "header.h"
header.h file
<if called by main.cpp>
#include "some_file_which_fails_when_used_with_OTHER_CPP.h"
<end if>
The typical way to do this is to expect source files to #define a macro prior to including the header:
// the_header.h
#ifndef MY_HEADER_H_INCLUDED
#define MY_HEADER_H_INCLUDED
#ifdef MY_PROJECT_MAIN
// ...
#else
// ...
#endif
#endif
In files using the header's "default" behavior
// some_code.cpp
// Just use the header
#include "the_header.h"
In files using the header's activated behavior:
// main.cpp
// Make sure this is BEFORE the #include
#define MY_PROJECT_MAIN
#include "the_header.h"
Ok so, simply said : I've included a .h into another .h and i get a compilation error telling me that the functions are already defined in main.obj
But, well i've only included Graphics.h one time so how can it be possible that main.obj also defined the Graphics.h functions ?
I got an Error LNK2005 "Already defined in main.obj".
Graphics.h contain functions that many others files will need, but for the moment we have a problem with just one file so I'd like to fix that first.
EDIT : SOLVED by spliting the header, i kept the header for the functions prototypes and I created a new Graphics.cpp for the functions definition
Here are the most concerned files, I've commented the files content so it is readable.
If I'm wrong by commenting please tell me and I'll put it on pastebin or something like that
main.cpp
#include "main.h"
using namespace std;
int main()
{
sMainData data = {};
main_Initialize(data);
while (data.config.window.isOpen())
{
main_Event(data);
main_Update(data);
main_Draw(data);
}
return 0;
}
main.h file :
#ifndef MAIN_H
#define MAIN_H
#include <SFML/Graphics.hpp>
#include "PlayerClass.h"
// Structures...
// Prototypes...
// Functions...
#endif // !MAIN_H
PlayerClass.h file :
#ifndef PLAYERCLASS_H
#define PLAYERCLASS_H
#include "AliveClass.h" // Including the mother
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include "Graphics.h" // <-- So here we have our man
//Class definition
#endif // !1
Graphics.h file :
#ifndef GRAPHICS_H
#define GRAPHICS_H
#include "SFML/Graphics.hpp"
// Prototypes...
// Functions...
#endif // !GRAPHICS_H
You didn't provide a minimal reproducible example, but my best guess is, you have some function implemented in the header file, while ending up including that header, either directly or indirectly, in more than one cpp file. The result is exactly the same function with exactly the same signature, being compiled in both cpp files, which causes the linker to complain.
Solutions:
Move the function out of the header and into its own cpp file (probably the best)
Find a way to only include the header in one single cpp file (probably the second best in case the header isnt yours and you don't want to touch it)
Make that function inline (probably the easiest, but technically the worst)
In a header file functions.h, the first two statements are defining FUNCTIONS_H if not already defined. Can someone explain the reason for this action?
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
void print();
int factorial(int);
int multiply(int, int);
#endif
The article you linked isn't about Makefiles at all, it's about compiling multi source file code.
Those are so called include guards. They prevent code from being included unnecessarily multiple times.
If FUNCTIONS_H is not defined then include the content of the file and define this macro. Otherwise, it's defined so file was already included.
There is also #pragma once serving the very same purpose, which although not being in the standard, is supported by many major compilers.
Consider example:
There are also two next header files - func1.h and func2.h. Both have #include "functions.h" inside.
If in main.cpp we do:
#include "func1.h"
#include "func2.h"
// rest of main...
The code will preprocessed to:
#include "functions.h"
// rest of func1.h
#include "functions.h"
// rest of func2.h
// main...
Then:
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
void print();
int factorial(int);
int multiply(int, int);
#endif
// rest of func1.h
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
void print();
int factorial(int);
int multiply(int, int);
#endif
// rest of func2.h
// main...
As you can see if not for include guards, the prototypes for functions would appear for second time. There could be also other crucial things, which redefinition would be causing errors.
It's an "include guard". It prevents redefinition if the header file is #included multiple times.
It's a C++ thing. It has nothing to do with makefiles.
Suppose I have the following header file:
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <string>
class TestClass
{
public:
TestClass();
std::string test();
};
#endif // TESTCLASS_H
Do I have to put a guard around #include <string> as well? If not, what if main.cpp also has #include <string>?
No, because the string header file has got its own include guards (as do the header files of all sensible libraries).
Not necesarry, the c++ standard libs have their own Guards.
I'm a bit confused at the moment because I'm planning to include multiple source and header files for the first time in one of my projects.
So I'm wondering if this would be the right approach?
Do I have to include the string header in every source file that uses it directly?
And what about the "stdafx.hpp" header that Visual C++ wants me to include?
Would that be the way to go?
main.cpp
#include "stdafx.hpp"
#include <string> //?
#include <stringLib1.h>
#include <stringLib2.h>
using std::string;
//use a windows.h function here
//use a stringLib1 function here
//use a stringLib2 function here
stringLib1.h
#include "stdafx.hpp"
#include <string>
using std::string;
class uselessClass1
{
public:
string GetStringBack1(string myString);
};
stringLib1.cpp
#include "stdafx.hpp"
string uselessClass1::GetStringBack1(string myString) {
return myString;
}
stringLib2.h
#include "stdafx.hpp"
#include <string>
using std::string;
class uselessClass2
{
public:
string GetStringBack2(string myString);
};
stringLib2.cpp
#include "stdafx.hpp"
string uselessClass2::GetStringBack2(string myString) {
return myString;
}
A good practice is usually to include only what your code uses in every file. That reduces dependencies on other headers and, on large projects, reduce compilation times (and also helps finding out what depends on what)
Use include guards in your header files
Don't import everything by polluting the global namespace, e.g.
using namespace std;
but rather qualify what you intend to use when you need it
You don't need stdafx.h in your project unless you're using precompiled headers. You can control this behavior in the VS project properties (C/C++ -> Precompiled Headers -> Precompiled Header)
The stdafx.h header is needed if precompiled header is enabled in VS. (Read this one)
You only need to include the stdafx.h in your .cpp files as the first include.
Regarding the header and cpp files (which come in pairs), include things necessary for the declaration in the header, and include everything else (necessary for the definition) in the cpp. Also include the corresponding header in its cpp pair too. And use include guards.
myclass.h
#ifndef MYCLASS_H // This is the include guard macro
#define MYCLASS_H
#include <string>
using namespace std;
class MyClass {
private:
string myString;
public:
MyClass(string s) {myString = s;}
string getString(void) {return myString;}
void generate();
}
myclass.cpp
#include <stdafx.h> // VS: Precompiled Header
// Include the header pair
#include "myclass.h" // With this one <string> gets included too
// Other stuff used internally
#include <vector>
#include <iostream>
void MyClass::generate() {
vector<string> myRandomStrings;
...
cout << "Done\n";
}
#endif
Then in main(...), you can just include myclass.h and call generate() function.
The stdafx include should be at the top of every .cpp file and it should NOT be in .h files.
You could put #include < string > in stdafx.h if you don't want to put it in every other file.
I suppose that you must be having your own header files also which might be requiring in other cpp files and header files. Like the one you gave
#include <stringLib1.h>
#include <stringLib2.h>
In my opinion, its better to create one common header file in which you include all the common library header files and your project header file. This file then you can include in all the other cpp files and header file. And it will be better to use header guards also.
So, considering a common header file "includes.h".
#ifndef INCLUDES_H
#define INCLUDES_H
#include <string>
#include <stringLib1.h>
#include <stringLib2.h>
/***Header files***/
#endif //INCLUDES_H
This is now your common header file. This you can include in all your project files.