Clarification on Includes in DLLs - c++

I recently came across something that goes against my understanding of includes.
I am creating a dll to hold basic coordinate objects for a personal game engine I'm developing (for fun).
Main dll header file.
#pragma once
#include "sclapi.h"
#include "vector.h"
#include "point.h"
// Other includes and stuff.
// Unimportant for this demonstration.
sclapi.h
#pragma once
#ifdef SCL_EXPORTS
#define SCL_API __declspec(dllexport)
#else
#define SCL_API __declspec(dllimport)
#endif
vector.h
#pragma once
// No includes
/*EDIT*/struct Point;
struct SCL_API Vector {
float x, y;
// Other stuff
explicit operator Point() const;
};
point.h
#pragma once
// No includes
struct SCL_API Point {
int x, y;
// Other stuff
explicit operator Vector() const;
};
My code works perfectly fine; but to my understanding, it shouldn't. A header file should only know what's declared in it (includes being shorthand for pasting in code). None of these objects are declared in the other's header files. [EDITED] point.h should have no knowledge of a Vector struct. Whats more, both even have knowledge of the SCL_API macro. If I comment out individual includes in the main header file, I get the expected compiler errors. What am I missing?
EDIT:
After further testing, I discovered that a declaration of the later objects needs to be in the first header file 'vector.h'; but after, they do not need to be declared again in any other header file. Also, declaring the classes in the main header file does not work. The Point forward declaration must be inside the vector.h file.

When you #include a file, it gets automatically "copypasted" into your source.
Because you included vector.h right before including point.h, the Point class will see it.
However, it's not a good idea to rely on this behavior as the order of includes might change and thus it will not work anymore, so you should #include "vector.h" in your point.h.

Related

Is it possible to add an include directive inside of a class definition?

I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.

If you include something in the .h file Do you have to include the same thing again?

So I am just wondering if you #include something in a for example header.h file:
For example this is called header.h:
#include <vector>
#include <iostream>
#include <somethingElse>
So if for example I make a file called something.cpp Do I need to put all those include statements again?
#include "header.h"
// If I include #header.h in this file. Do the #include carry over to this file. Or do they not
I am wondering because whenever I include <vector> something in my .h file the #include statements that I used previously in the .h file always turn grey which means they are not used. Is it because I used it in the .h file? Its not a problem or anything I am just curious.
You don't need to include those headers again because your compiler can find those headers. You can also try to read and understand the makefile (or CMakeList) which will help.
Try always to avoid "Multiple file inclusion" via using inclusion guard or #pragma once in order to prevent the multiple file inclusion.
To include file means that the content of the file will be added to the very place you wrote include.
Here's an example:
// header.h
const int vlaue = 10;
const int value2 = 0;
// main.cpp
#include "header.h"
#include "header.h"
Above the content of "header.h" is added twice to main.cpp.
Do you know what is the result? It's a compile-time error complaining of redefinition of value and value2.
In the above example I think green programmers don't get trapped by it but it is just an explanation, So what I talk about is when a huge program where many header files and many source files and some files include others then it'll be so difficult to track the right file inclusion.
The workaround that is to use inclusion guards or pragma once eg:
Let's modify our header.h to look like:
// header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
const int vlaue = 10;
const int value2 = 0;
#endif
Now in main.cpp:
#include "header.h"
#include "header.h"
#include "header.h"
The code above works fine and no duplicate of header content is added to main.cpp. Do you know why? It's the magic of Macro there. So at first time the pre-processor checks whether a macro has been already defined with the name MY_HEADER_H or not and for sure for the first time it is not defined so the content is added. The second and so on the condition fails because the macro is already defined thus the content of header.h will not be added to where it is called.
The draw back of inclusion guard is if you have a macro with same name as the inclusion guard thus it is already defined so the content will never be added (empty content). Thus you get a compile-time error:
value, `value2` undeclared identifiers.
The second solution is using pragma eg:
Let's modify our header.h file:
// header.h
#pragma once
const int vlaue = 10;
const int value2 = 0;
// main.cpp
#include "header.h"
#include "header.h"
The code above works correctly so no multiple inclusion of header.h That is because of the magic of pragma once: which is a non-standard but widely supported pre-processor directive designed to cause the current source file to be included only once in a single compilation. Thus, #pragma once serves the same purpose as include guards, but with several advantages, including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.
Finally you should include header wherever their content is used eg:
// Shape.h
class Shape{
// some code here
};
// Cube.h
#include "Shape.h"
class Cube : public Shape{
// some code here
};
// Cuboid.h
// #include "Shape.h"
#include "Cube.h" // So here the Shape.h is added to Cube.h and Cube.h is added here.
class Cuboid : public Cube{
// some code here
};
As you can see above the content of Shape.h is added to Cuboid.h indirectly because it is added to Cube.h and cuboid.h includes Cube.h so it is added to it. So without inclusion guards or pragma once if you include the two headers in one source file you get duplicate content there.

How to Include-guard when using multiple headers on a main.cpp?

I'm learning C++ in a course, using Visual Studio 2013, and I have an issue with include-guards on my main.cpp. I can't use either class or #pragma once (though they work) due to conditions my professor said.
If I only use Coordinates and Line, and I use in main.cpp the #include Line.h (which get code from both Line and Coordinates), this works ok, but when I add Rectangle and Triangle (both have #include "Line.h"), then it throws the "already defined" error LNK2005 several times.
Is there something missing?
This is my code:
Coordinates.h
#ifndef Coordinates
#define Coordinates
//Code declaration. Other headers have similar declaration
struct CoordinatesType { double x, y; } coordinates;
void setCoordinates(double x, double y);
CoordinatesType getCoordinates();
#endif
Coordinates.cpp
#include "Coordinates.h"
//Code implementation
Line.h
#ifndef Line
#define Line
#include "Coordinates.h"
//Code declaration
#endif
Line.cpp
#include "Line.h"
#include <math.h>
//Code implementation
Rectangle.h
#ifndef Rectangle
#define Rectangle
#include "Line.h"
//Code declaration
#endif
Rectangle.cpp
#include "Rectangle.h"
//Code implementation
Triangle.h
#ifndef Triangle
#define Triangle
#include "Line.h"
//Code declaration
#endif
main.cpp
#include "Triangle.h"
#include "Rectangle.h"
int main(){
//Do stuff here.
}
If you need me to add the implementation and declaration codes, let me know, but I feel like it has to do with the include-guard.
EDIT: I'll add code in the Coordinate header so you can get an idea of what I'm doing and to avoid consuming a lot of space in the post. Remember, I can't use class Coordinates{} due to my professor's restriction to not use it.
This error is a linker error, not a compiler error.
Header guards do nothing for the linker.
You have successfully guarded against multiple declarations of things within the same translation unit, but you have not guarded against multiple definitions of things across your whole program.
The way to guard against that is to, well, not do that. There should be no non-inline, non-template definitions of anything in your header if you want to include it into multiple source files.
Here, you declare a type CoordinatesType, and create an object of that type:
struct CoordinatesType { double x, y; } coordinates;
Don't do that! Create an instance of CoordinatesType only in a source file, not in a header. Otherwise, every source file that includes this header (directly or indirectly) will get its own coordinates object and your linker complains about the name collision.
The code should be:
struct CoordinatesType { double x, y; };
Then, either coordinates in the one source file in which you wish to use the object… or extern on its declaration in a header. There are better approaches but I shan't enumerate them all here since this topic has been covered to death on SO already. Furthermore, your C++ book will have an explanation.
But the long and short of it is that this has nothing to do with header guards.
As already pointed out, your problem has nothing to do with include-guards.
Your problem is in this line:
struct CoordinatesType { double x, y; } coordinates;
While the declaration of the struct
struct CoordinatesType { double x, y; };
may appear in multiple .cpp files, as long as it is identical (it is, since you include the same header-file), you also define a variable
CoordinatesType coordinates;
in the same line. Since a definition is only allowed once, your linker complains.
If you really need a global variable of that type (check if you really need one, as it might not be necessary), change your header to a declaration:
struct CoordinatesType { double x, y; };
extern CoordinatesType coordinates;
and use a definition
CoordinatesType coordinates;
in exactly one cpp-file.
Note that the error didn't happen when only including Line and Coordinates, because your include-guards work and you only include the headers in a single .cpp file
Coordinates.h doesn't have any include guard.
When you include it multiple times, it defines Coordinates only once, but the rest of the file is included multiple times.
Put the #endif in the right place.
PS. The identifiers used in the include guards should be something that is never, ever used elsewhere by coincidence. I wouldn't be surprised if someone tried to use a variable named Line or Triangle. And since you #define those, that will lead to very unexpected errors. Use something like #define LineHeader_Included__ .

How to use the same header files in different classes to avoid "use of undefined type"

I'm currently writing a simple game with a 2D library and as C++ is a new language to me and as Java is my first fluent programming language, perhaps some bad habits are flowing through to this language that I don't fully understand. I have never had problems doing this in Java but in C++ it causes a ton of errors. As I don't want everything crammed into one class/header file, I've decided to split them up into packages and different classes, but I can't seem to do this without includng the same header files in different places. Here's an example.
Project.h
#ifndef PROJECT_H
#define PROJECT_H
#include "UIManager.h"//this is causing the error, when this, and the class instance is removed the program compiles and runs fine without error
using namespace gamelib;
class Project : public Game {
public:
Project(int argc, char* argv[]);
~Project();
void Update(int elapsed);
void Draw(int elapsed);
void Load();
/*Background*/
Texture * background;
Rectangle* backgroundRectangle;
UIManager ui;
};
#endif
UIManager.cpp
#include "UIManager.h"
void UIManager::load() {
startMenuBackground = new Texture();
startMenuBackground->Load("Sprites/Interface/Transparency.png", false);
startMenuRectangle = new Rectangle(0.0f, 0.0f, Graphics::GetWidth() / 2, Graphics::GetHeight() / 2);
}
UIManager.h
#ifndef UIMANAGER_H
#define UIMANAGER_H
#include "Project.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif
Now I need all of these includes so I can store the necessary textures, and the Texture and Rectangle come from the API that is being used as a namespace in Project.h
I also need a class instance in Project.h, UIManager ui; So i can use this in the Project.cpp file to call methods
How can I get around this without getting all these errors?
If I understand your problem correctly, you want to avoid including header files multiple times. In that case, what you should do is using Include guards. Which makes sure that the header is included once. Optionally you can use #pragma once at the top of your file but that's another discussion.
Example:
#ifndef UIMANAGER_H // you may choose another name than "UIMANAGER_H"
#define UIMANAGER_H
// Your header file code and includes here.
// Do this for your header files.
#endif
Now, do the same for the other header file but instead naming the macro PROJECT_H or similar.
A good practice is to add in the beginning and in the end of the .h files:
#ifndef FILENAME_H
#define FILENAME_H
//Your code here
#endif
Where FILENAME_H is unique for each .h file.
Those are compiler predirectives, which are not included in the executable, but changes the way that the compiler acts.
Adding those, the compiler won't add the same file twice for the same file. If it's already loaded, it won't load it.
Take in account than in C++, header files are parsed independently on each file of the project.
Typically, the fix would be to change your code to this...
#ifndef UIManager_H
#define UIManager_H
// It's pretty normal to put each class in its own header file.
#include "Texture.h"
#include "Rectangle.h"
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
Since you never instantiate either object though, you don't strictly need a full header.
#ifndef UIManager_H
#define UIManager_H
// Since we only use pointers to the classes, we can forward declare the classes
class Texture;
class Rectangle;
class UIManager {
public:
void load();
private:
Texture * startMenuBackground;
Rectangle * startMenuRectangle;
};
#endif // UIManager_H
You can use the macros #ifndef and #define. This is a common pattern. For example, in your UIManager.h file, have the following:
#ifndef __UI_MANAGER_H__
#define __UI_MANAGER_H__
#include "Project.h"
//Rest of UIManager class definition
#endif
In you Project.h file, have the following:
#ifndef __PROJECT_H__
#define __PROJECT_H__
#include "UIManager.h"
//Rest of Project class definition
#endif
This allows the compiler to compile without errors when it sees circular includes. But it's more preferable to use class forward declaration if possible, but this is a completely different topic.
The macro names __UI_MANAGER_H__ and __PROJECT_H__ are purely randomly chosen. You can choose to use a different naming convention.

Multiple inclusion in multiple files

I am making a small game.
In BattleRecord.h:
#ifndef _CHARACTER_H_
#define _CHARACTER_H_
#include "Character.h"
#endif
class BattleRecord
{
public:
Character Attacker;
Character Defender;
Status status;
int DamageDealt;
int GoldEarned;
int ExpGained;
};
In Character.h:
#ifndef _EQUIPMENT_H_
#define _EQUIPMENT_H_
#include "Equipment.h"
#endif
class BattleRecord;
class Character
{
BattleRecord AttackEnemy(Character &Enemy);
}
In BattleRecord.h:
#ifndef _CHARACTER_H_
#define _CHARACTEr_H_
#include "Character.h"
#endif
#ifndef _BATLE_RECORD_H_
#define _BATLE_RECORD_H_
#include "BattleRecord.h"
#endif
class GUI
{
public:
//GUI Methods, and two of these:
void ViewStats(Character &Player);
void Report(BattleRecord Record)
}
The problem here is, my Character.h and BattleRecord.h need to include each other, and this definitely will cause multiple redefinition problem. Therefore, I used forward declaration in Character.h by adding:
class BattleRecord;
The problem is sovled. But then, the GUI.h needs BattleRecord.h again for reporting the battle, so I have to include BattleRecord.h into the GUI.h. I also have to include the Character.h in order to pass into the ViewStat function. I got error and stuck with this up to this piont.
You're using inclusion guards wrong. They should appear in the file that you intend to prevent multiple inclusions only, and they should cover the entire file. (not just the includes).
For example, in BattleRecord.h
#ifndef _BATTLE_H_
#define _BATTLE_H_
#include "Character.h"
class BattleRecord
{
public:
Character Attacker;
Character Defender;
Status status;
int DamageDealt;
int GoldEarned;
int ExpGained;
};
#endif // _BATTLE_H_
Put your #endif at the end of the file not the end of your includes or use #pragma once at the top if your compiler supports this although that is less portable.
Edit:
To further explain what #ifdef & ifndef does is tell the compiler to include or exclude code entirely from compilation.
// if _UNQIUEHEADERNAME_H_ is NOT defined include and compile this code up to #endif
#ifndef _UNQIUEHEADERNAME_H_
// preprocessor define so next time we include this file it is defined and we skip it
#define _UNQIUEHEADERNAME_H_
// put all the code classes and what not that should only be included once here
#endif // close the statement
The reason you want to do this is because including a header file is basically saying "put all the code in this file here" if you did that multiple times then you'd have naming conflicts from redefining objects and slow compile times in the best scenario.
In general, use forward declaration instead of includes. This minimizes how many includes you include file contains. The only exception is when the class you are defining is a derived class, then you need to include the base class.
In addition to the include guard issues mentioned above (you also have a _CHARACTEr_H_/_CHARACTER_H_ mismatch that might cause you trouble on line 2 of GUI.h), you may want to revise your object design so that the Character does not AttackEnemy(), but rather there is a Battle() class where two Characters are referenced and a BattleRecord is produced after the battle. This would prevent the Character class from ever having to know about BattleRecords in the first place, would allow for the possibility of multi-Character battles in the future, having multi-turn battles, or having special battles through inheritance of the Battle class.
OK everyone,
Thanks for helping me. I have rewritten all the inclusions for the header files as suggested, and it works flawless now. Take quite time a bit of time since I did it wrong for many classes.