Mayer M Mayer M - 1 year ago 47
C++ Question

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

I'm learning C++ on a course, using Visual Studio 2013, and I have an issue with include-guards on my main.cpp. I can't use neither

#pragma once
(though they work) due to conditions my professor said.

If i only use
, and I use in
#include Line.h
(which get code from both
), this works ok, but when I add
(both have
#include "Line.h"
), then it throws the "already defined"
error LNK2005
several times.

Is there something missing?

This is my code:

#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();

#include "Coordinates.h"
//Code implementation

#ifndef Line
#define Line
#include "Coordinates.h"
//Code declaration

#include "Line.h"
#include <math.h>
//Code implementation

#ifndef Rectangle
#define Rectangle
#include "Line.h"
//Code declaration

#include "Rectangle.h"
//Code implementation

#ifndef Triangle
#define Triangle
#include "Line.h"
//Code declaration

#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.
Anyways, thanks in advance

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.

Answer Source

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.