pragma or ifndef?

I was finishing up an exam my professor gave me with only part of the .h file to answer some multiple choice questions. I wanted to try and figure out where he was going to go with his code so I decided to try and make a program that I could bring to him to see if I am starting to understand what he is teaching in data structure and algorithms. The problem is that right now I can't even build it to test anything or go further. He taught us to use #ifndef especially in our .h in our .cpp file that holds our definitions and then just #include in our main.cpp. I was getting a linking error saying that it was already defined in my obj file. I then researched how to try and fix it and came upon using #pragma once was cleaner and newer compiler's are using that instead. Can anyone shed some light of which one is a better practice? Is #ifndef an ancient way of checking for multiple file inclusion? Or am I doing something wrong? In the code that follows I am going to comment out both the pragma and the ifndef where I used it just so you can see the whole scope.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//My header file
  //#pragma once
//#ifndef COINSORTER_H
//#define COINSORTER_H


#include <string>
#include <iomanip>

using namespace std;


class CoinSorter
{
public:
	static const string DEFAULT_COUNTRY;

	// These constructors don't create any coin types;
	// instead, setTypes() will create the coin types.
	CoinSorter();  // default country
	CoinSorter(const string &initCountry);

	// Copy constructor
	CoinSorter(const CoinSorter &otherSorter);

	// Assignment operator
	CoinSorter &operator =(const CoinSorter &otherSorter);

	// Destructor
	~CoinSorter();

	// Accessors and mutators

	//get
	int getCount(int count);


	//add
	void addType(int type);

	

	// Create all coin types with space to store counts.
	// This function may be called more than once with
	// a different number of types each time.
	void setTypes(int newNumTypes);

	

	private:
		 string country;
		int *counts;  // store dynamic array for count of each type
		int numTypes;  // size of dynamic array
};
//#endif


//My definitions .cpp 
//#pragma once
//#ifndef COINSORTER_H
//#define COINSORTER_H

#include <iostream>
#include "CoinSorter.h"

using namespace std;

//constructors
CoinSorter::CoinSorter()
{
	country = DEFAULT_COUNTRY;
}

CoinSorter::CoinSorter(const string &initCountry)
{
	country = initCountry;
}

//copy constructor
CoinSorter::CoinSorter(const CoinSorter &otherSorter)
{
	//copy non dynamic array
	numTypes = otherSorter.numTypes;

	//allocate new array
	counts = new int[numTypes];

	//copy non dynamic array 
	for (int i = 0; i < numTypes; i++)
	{
		counts[i] = otherSorter.counts[i];
	}
}

//assingmnet operator
CoinSorter & CoinSorter::operator=(const CoinSorter & otherSorter)
{
	if (this != &otherSorter)
	{
		// deallocate
		delete[] counts;

		//allocate
		numTypes = otherSorter.numTypes;

		//allocate the size

		counts = new int[numTypes];

		for (int i = 0; i < otherSorter.numTypes; i++)
		{
			counts[i] = otherSorter.counts[i];
		}
		
	}
	return *this;
}
//destructor
CoinSorter::~CoinSorter()
{
	delete[] counts;
	counts = NULL;
	numTypes = 0;

}

int CoinSorter::getCount(int count)
{
	return counts[count];
	
}

void CoinSorter::addType(int type)
{
	int i;
	for (i = 0; i < numTypes; i++)
	{
		if (counts[i] == int())
		{
			counts[i] = type;
			return;
		}
	}
}





// Accessors and mutators

	// Create all coin types with space to store counts.
	// This function may be called more than once with
	// a different number of types each time.

void CoinSorter::setTypes(int newNumTypes)
{
	numTypes = newNumTypes;
	counts = new int[newNumTypes];
}

//#endif


//My Main
//#pragma once
//
//


#include <iostream>
#include <string>

#include "coinSorter.cpp"

using namespace std;

int main()
{

	const int TYPES = 3;
	//types is the coin itself
	CoinSorter france("France");


	france.setTypes(TYPES);

	for (int i = 0; i < TYPES; i++)
	{
		france.addType(TYPES + i);
	}

	for (int i = 0; i < TYPES; i++)
	{
		cout << france.getCount(i);
	}

	
	return 0;
}
Last edited on
closed account (z05DSL3A)
If I'm reading your code properly, don't use import guards in your cpp files only your headers.

Can anyone shed some light of which one is a better practice? Is #ifndef an ancient way of checking for multiple file inclusion?
I don't know about best practice but I tend to use both at the same time. There is a small difference between the two but it's hardly noticeable. using both means that if the compiler does not understand pragma once then it rolls over to the venerable ifndef.
Last edited on
closed account (E0p9LyTq)
#pragma is non-standard, not every compiler supports it.

Every compiler worth using does understand #ifndef/#define/#endif header guards.

Header guards, as the name implies, should only be used in header files. Never in .c/.cpp source files.
Line 174: You should be including coinsorter.h, not consorter.cpp. NEVER include a .cpp file. That will give you duplicate defined symbols at link time.

As for #pragma once verses, #ifndef, I prefer #pragma once as I find that cleaner and all compilers that I work with support it. However, as already pointed out, not all compilers support #pragma once.
About #pragma once vs. include guards:

It's probably obvious that the former is easier to write. While it is not part of standard C++, it is ubiquitous anyway.

However, once has a subtle disadvantage in that it relies on the implementation's interpretation of file identity. For instance, if a source file is copied or hard/soft linked, it isn't clear whether or not the copy (or the link) refers to the same file and needs to be be included twice. Include guards sidestep this issue by associating a unique ID to file contents.

IIRC, the issue of file identity is part of the reason why this pragma (or an equivalent feature) was never standardized. If you are not doing weird things with your source files, it probably doesn't matter.

(I prefer include guards, despite the increased possibility of typos.)
Last edited on
Last edited on
Line 174: You should be including coinsorter.h, not consorter.cpp. NEVER include a .cpp file. That will give you duplicate defined symbols at link time.

The thing is that when you give the compiler a file (lets call it X), the compiler will run preprocessor on X.
The preprocessor essentially finds "header file" mentioned in '#include' and copy-pastes it into X in place of the include.
Those headers probably include something too, so the preprocessor repeats "recursively" until (copy of) X (in memory) is all code and no #***.

The inclusion guards (pragma or ifndef) prevent preprocessor from copy-pasting multiple copies of same header file's code into X. Without the guards the compiler will see the repeats as a fatal error.

Finally, compiler compiles code in X into object file. There can be more than one file to compile.
Linker combines the object files into executable.


A build system / IDE probably compiles each .cpp-file in the project by default.
The convention is that you want an object file from each .cpp-file.


If your build system compiles both coinSorter.cpp and main.cpp separately and the main.cpp includes code of coinSorter.cpp, then the object file generated from main.cpp contains same instructions as the object file created from coinSorter.cpp. The linker will see the repeating "symbols" as a fatal error.


IF you NEVER include a .cpp file, THEN you follow the convention and have less errors.


Use the standard, follow the convention.
the only pragmas you should use are to do things that you cannot do any other way (like turn off the bogus 'deprecation' of legit c++ code in M$). Do not use them for include guards or normal constructs.
> Can anyone shed some light of which one is a better practice?

There are advantages and disadvantages for both.

#pragma once is non-standard, but supported by every mainstream C++ compiler.

Unlike header guards, this pragma makes it impossible to erroneously use the same macro name in more than one file. On the other hand, since with #pragma once files are excluded based on their filesystem-level identity, this can't protect against including a header twice if it exists in more than one location in a project.
https://en.cppreference.com/w/cpp/preprocessor/impl



We could use both, if we want. For example:
1
2
3
4
5
6
7
8
9
#pragma once

#ifndef MY_HEADER_H_INCLUDED
#define MY_HEADER_H_INCLUDED


// ...

#endif // MY_HEADER_H_INCLUDED 

Last edited on
closed account (E0p9LyTq)
Can anyone shed some light of which one is a better practice?

There will be people on either side who will fight to the digital death for their Proper Usage as Holy Writ.
Thank you everyone to shed some light on this matter. AbstractionAnon I am including the header file inside the definition .cpp file and then including then including that cpp file in my main because that is the way my professor has shown me. He stated that while including the cpp file inside my main that the header file will automatically come with it since it is included in the definition cpp file. Now that you have brought it up I will try it the way that you suggest, however I might still have to do it his way while in his class. I have another question that would love some information on is that I am not the type to come up with clever programs to write myself. But people have talk about websites to go to that gives you problems to work on such as Odin, codeingames3 or code chef. Do you know any others that will help with algorithms?
Funny how these topics reappear so regularly.

#pragma once was once very popular. It is still supported by every modern compiler.

Moreover, every modern compiler does it even without the #pragma once directive.


The Problem
Pragma once / filename tracking can be defeated. This is not an abstract, if non-obvious problem.

The basic issue is that it is easily possible to produce multiple names for a single file. Or to duplicate a file’s content in another location.

Very large systems with hundreds of developers do struggle with these issues.


The only solution that cannot be defeated
...remains using include guards — if done correctly.

Because you can still screw up. The first is a rather obvious issue: you can choose a dumb name that conflicts with another library, like STRING_H. This isn’t so bad, except that it easily leads to the second problem:

Identical libraries with different include guards.


Best practice
Always, always, always use include guards. Make your include guards unique, when you first create the file. Personally, I use something that cannot be confused:

1
2
3
4
5
6
7
8
9
10
#ifndef DUTHOMHAS_STRING_HELPERS_201903121140_HPP
#define DUTHOMHAS_STRING_HELPERS_201903121140_HPP

namespace duthomhas {

  ...

}

#endif 

Yep. That’s the date I first created that include guard / library file, encoded right along with my unique name and file function.

This will never conflict with anyone else’s library (unless the conflict is intentional). No matter how the file / content / whatever is duplicated, the unique include guard gets carried right along with it.

The next point is also essential: when available, keep everything in a proper namespace.
Include guards protect against multiple identical symbols when compiling; namespaces protect against multiple identical symbols when linking.


If, in addition, you wish to add the #pragma once directive, there is no really good reason not to. (It might screw up the auto-detection of an extant compiler, but, as already mentioned, modern compilers can handle it with grace. Those that cannot will fall back to the include guard, as designed.)

So, don’t be surprised to find:

1
2
3
#include once
#ifndef MYFOO_SOMETHING_UNIQUE_HPP
#define MYFOO_SOMETHING_UNIQUE_HPP 

Perfectly acceptable. Guaranteed not to break — but only because of the unique include guard.


However, as the ISO committee recommends, using #pragma once is now more of a crutch than anything useful. I think it rightly recommends discontinuing use. Again, all modern compilers already perform its function regardless of whether or not it is present.

Use unique include guards. Please don’t do it any other way.
Topic archived. No new replies allowed.