What is `#ifndef FUNCTIONS_H` in functions.h for? - c++

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.

Related

One time included .h functions already defined in main.obj

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)

Class does not name a type with header guard

Due to error, I needed to implement a header guard in my Header file and Cpp since I have never used it before I don't know what went wrong because on some classes it works and on one it just won't... Originally the problem was bigger, but I think I narrowed it down to the origin of the problem.
LedHandler.h
#ifdef LED_HANDLER_H
#define LED_HANDLER_H
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <FastLED.h>
/* #include "Led/LedFunction.h"
#include "Led/LedStates.h"
#include "Led/Fading.h" */
class LedHandler {
public:
LedHandler(int length, uint16_t pin);
void clear();
void show();
void setColor(int s, int r, int g, int b);
Adafruit_NeoPixel getStrip();
int getLength();
private:
/* LedStates &currentState;
LedStates &targetState;
Fader<LedStates> &ledFader; */
int length;
Adafruit_NeoPixel strip;
CRGB* leds;
};
#endif
LedHandler.cpp
#ifdef LED_HANDLER_H
#define LED_HANDLER_H
#include <Adafruit_NeoPixel.h>
#include <FastLED.h
#include "Handlers/LedHandler.h"
LedHandler::LedHandler(int length, uint16_t pin) {
...
}
...
#endif
main.cpp
#define FASTLED_ESP8266_NODEMCU_PIN_ORDER
#include <Arduino.h>
#include <Scheduler.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include "Tasks/WifiTask.h"
//#include "Tasks/Networking/UDPTask.h"
//#include "Handlers/GsonHandler.h"
#include "Handlers/LedHandler.h"
LedHandler ledHandler(60, D6);
Error
src\main.cpp:14:1: error: 'LedHandler' does not name a type
LedHandler ledHandler(60, D6);
^
*** [.pio\build\nodemcuv2\src\main.cpp.o] Error 1
As noted by walnut in comments, first issue is that #ifdef should be #ifndef. Now this directive can never be evaluated to true (because this macro is not defined anywhere).
Also, you shouldn't ever put include guards in your cpp file. As the name suggests, you use them to protect files that included in other files, and cpp files should never be included anywhere.
Now, with include guard in your cpp file, the following happens:
Code is read from top to bottom
ifndef is encountered, it is true (LED_HANDLER_H is not yet defined)
LED_HANDLER_H is defined
Other headers are included
"Handlers/LedHandler.h" is included
Now, it's important what #include directive does. It's a simple copy-and-paste of the file content into another file.
#ifdef LED_HANDLER_H from inside LedHandler.h is checked, and it's false (this macro is already defined in step 3)
The whole content of LedHandler.h is skipped due to include guard.

Global variable error C++

I'm having an error I don't know how to fix in my large Operating Systems homework. The error I'm getting is "42 duplicate symbols for architecture x86_64". I presume this is to do with my global variables file "global.h". I have 3 global variables I use and "global.h" is included in an abstract class called "PageReplacementAlgorithm.cpp". I have around 6 classes that are derived from the PageReplacementAlgorithm class and they utilize these global variables. I think the problem comes in when I include all these derived classes in my "main.cpp" as I need to make new instances of them. How can I fix the implementation of the global variables?
Global.h
#include "PageTableEntry.h"
using namespace std;
#ifndef Global_H
#define Global_H
extern PageTableEntry pageTable[64];
extern int* frameTable;
extern int framesCount;
#endif
PageReplacementAlgorithm.h
#include "Global.h"
using namespace std;
#ifndef PageReplacementAlgorithm_H
#define PageReplacementAlgorithm_H
class PageReplacementAlgorithm {
public:
virtual int selectFrame(PageTableEntry &p) = 0;
};
#endif
Example Derived Class (FIFO)
include "PageReplacementAlgorithm.h"
using namespace std;
#ifndef FIFO_H
#define FIFO_H
class FIFO : public PageReplacementAlgorithm {
public:
FIFO();
int selectFrame(PageTableEntry &p);
private:
int entries;
};
#endif
Main.cpp
#include "Aging.cpp"
#include "Clock.cpp"
#include "FIFO.cpp"
#include "MMU.cpp"
#include "NRU.cpp"
#include "Random.cpp"
#include "SecondChance.cpp"
Why do you include all cpp files in main.cpp? I think they contain same includes, right? Even you have the guards there, you do additional includes before that guards and that is probably the source of problems. The main.cpp could contain just main() function and import headers of your classes, there is no need to include cpp.
Also, you can modify your header files to look like this (for sake of extreme safety):
#ifndef PageReplacementAlgorithm_H
#define PageReplacementAlgorithm_H
#include "Global.h"
using namespace std;
...
#endif
I recommend you to look at answer C++ #include guards
If you get rid of #include "(anything).cpp, things should work much better. When you build the project, or run the compiler e.g. g++ main.cpp foo.cpp, that's when those .cpp files get built and linked into your program.

C++ Header Guards

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.

C++ - How can I avoid this header from appearing twice?

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.