#Header guards

1 messages · Page 1 of 1 (latest)

smoky vale
#

it's something you put in your files (the headers) to prevent the content from being included multiple times

feral swift
#
// some_header_file.hpp
#ifndef SOME_HEADER_FILE_HPP
#define SOME_HEADER_FILE_HPP

// contents of header

#endif //SOME_HEADER_FILE_HPP
#

it's basically wrapping the contents of the header file in macros similar to these ones

vital crystalBOT
#

@weary sphinx has reached level 1. GG!

smoky vale
#

yes

#

but even without header guards you can

#

what header guards solve is when one .cpp file includes a header multiple times, either directly or indirectly

#

by indirectly I mean, you have file.cpp, a.h b.h and c.h
if file.cpp include a.h and b.h
and both a.h and b.h include c.h
then it's like file.cpp includes c.h twice

feral swift
#

but header guards prevent the duplication of the code contained in c.h

smoky vale
#

sure

#

but with better names

#

or just use #pragma once

steel egret
#

No, in your example, header guards are unnecessary, because "get.h" is included only once in every compilation unit. Also, what is "square.h"?

The problem is if your program looks something like this:

get.h

#ifndef get
#define get

int getOne(); 
int getTwo(int sideLength);
struct Getter { int x, int y};

#endif

square.h

#include "get.h"

void processSquare(Getter g);

main.cpp

#include "get.h"
#include "square.h"
#include <iostream>

int main()
{
    std::cout << "a one has " << getOne() << '\n';
    std::cout << "a one * 2 is " << getTwo(2) << '\n';

    return 0;
}

To understand it better, remember that the headers are just copy-pasted into the source code.

main.cpp after preprocessing with header guards:

// get.h
int getOne(); 
int getTwo(int sideLength);
struct Getter { int x, int y};

// square.h
// get.h is skipped because the header guard turns off all the definitions in that file
void processSquare(Getter g);

// iostream
[... iostream definitions ...]

int main()
{
    std::cout << "a one has " << getOne() << '\n';
    std::cout << "a one * 2 is " << getTwo(2) << '\n';

    return 0;
}

main.cpp after preprocessing if you remove header guards:

// get.h
int getOne(); 
int getTwo(int sideLength);
struct Getter { int x, int y};

// square.h
// square.h includes full get.h header
int getOne(); 
int getTwo(int sideLength);
struct Getter { int x, int y};

void processSquare(Getter g);

// iostream
[... iostream definitions ...]

int main()
{
    std::cout << "a one has " << getOne() << '\n';
    std::cout << "a one * 2 is " << getTwo(2) << '\n';

    return 0;
}
#

But yeah, header guards are an old solutoin, #pragma once is the way to go now.

feral swift
#

generally, the convention is to take the file name, replace the dot with an underscore and convert it to uppercase for the macro you're defining

#

so get.h becomes GET_H

smoky vale
#

For the vast majority of people it's perfectly fine

feral swift
#

i do not care

smoky vale
#

lol

steel egret
#

It's more portable than some of the C++17 features 🙂