1

I have a class called "Animal" which is a super-class and pure polymorphic. I have other classes "Dog", "Cat", "Hamster" etc.. that all inherit from the "Animal" class.

In a program, I need to include all of the sub-classes (dog, cat, hamster) however, when I do:

#include "Hamster.h"
#include "Dog.h"
...
...

I get the error:

previous definition of ‘class Animal’

Is there a way to prevent this?

P.S. I have thought about doing a:

#ifdef

But, for if the class get's used, then include it. E.g. if the program is trying to instigate a Cat class, then, carry out the include.

Sorry if this isn't explained well.

Phorce
  • 2,632
  • 13
  • 43
  • 76

4 Answers4

7

Use include guards in header files:

#ifndef ANIMAL_H
#define ANIMAL_H

//definitions

#endif
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
5

At the top of each header, put a

#pragma once

The international standard just says the compiler must ignore this if it doesn't understand it.

But nearly all compilers do understand it, it's a de facto standard.

An alternative to the #pragma is to use

#ifndef MYHEADER_H
#define MYHEADER_H

// Contents of header

#endif

which is more ugly, more verbose, less easy to get right, can fail through name collision, and can be less efficient, but which is wholly standard.

Anyway, the idea is to prevent the header contents, like class definitions, from being included twice or more in the same translation unit.

Note, however, that you can do identical typedefs in the same translation unit.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • and hth. - AlfCh Hello, so I have: #pragma once #include "../Animals/Cat.h" #include "../Animals/Dog.h" (obviously on different lines) BUT still shows the error. Any ideas? Cheers – Phorce Oct 29 '12 at 14:53
  • For a defacto standard, it doesn't seem to be widely used. At least, I've never seen it in production code (including under Windows). And of course, with or without `#pragma once`, you still need the include guards, since there's no reliable way a compiler can tell that it is dealing with the same file. (The fact that it can not be implemented reliably is why the standards committee rejected it.) – James Kanze Oct 29 '12 at 14:56
  • 1
    @Phorce: you put it at the top of each header file, not before a collection of main program's include directives – Cheers and hth. - Alf Oct 29 '12 at 14:56
  • @James: you might read up on the linked-to Wikipedia article. in them old days, g++ had some problems with symbolic links, so then your statement about "the same file" and "not reliably" was correct. it no longer is correct. – Cheers and hth. - Alf Oct 29 '12 at 14:58
  • g++ doesn't like #pragma once – Phorce Oct 29 '12 at 15:01
  • @Phorce: that assertion is wrong. you need to *demonstrate* such a statement, through example, to get beyond the pure assertion stage, to normal debate. then you would probably have convinced yourself that it was wrong before posting it. – Cheers and hth. - Alf Oct 29 '12 at 15:02
  • I don't know why I care to post SO answers at all. With a system actively suppressing normal debate it invariably encourages the mindless to post contrary but unsubstantiated opinions. Trying to give good advice or correct technical facts on SO, is just like pearls before swine. – Cheers and hth. - Alf Oct 29 '12 at 15:06
  • @Cheersandhth.-Alf I agree with you, in some respect. I am grateful for your help. I tried the #pragma though and got a warning. No specific warning either. – Phorce Oct 29 '12 at 15:12
  • @Phorce: g++ 4.7.1 does not warn about `#pragma once` even with `-Wextra`. so the warning you saw was probably *completely unrelated*. anyway, again, to move above vague beliefs and assertions, you need to create and provide complete examples. – Cheers and hth. - Alf Oct 29 '12 at 15:26
  • @Alf My statement is correct. It is impossible to implement a totally reliable `#pragma once`, period. And it has nothing to do with symbolic links, but rather with remote file systems. The best you can do is implement a non-perfect version, which can, under certain circumstances, reopen the same file, thinking it is different. The compiler can't know more than the OS it's running under, and the OS itself generally cannot distinguish whether two remotely mounted files are identical or not. – James Kanze Oct 29 '12 at 15:43
  • @James: your statement is incorrect. it is true that with remote file systems one can do things that foul up `#pragma once`, and it is also true that just with local file systems one can do things that foul up ordinary header guards. to the degree that that is an argument about `#pragma once`, it favors `#pragma once` (it is indeed the main reason why some people prefer `#pragma once`), and not, as your statement erroneously seemed to indicate, the opposite. – Cheers and hth. - Alf Oct 29 '12 at 15:50
  • @Alf In all probability, g++ simply ignores `#pragma once`. That's what compilers are supposed to do with pragmas they don't understand. At any rate, the exact string `"once"` doesn't occur outside of error messages in the compiler binary. (I know, this doesn't prove anything, since the compiler _could_ use a trie or some such to look it up. But I'd bet against it.) – James Kanze Oct 29 '12 at 15:52
  • @James: re " In all probability, g++ simply ignores #pragma once.", please stop spouting **pure fantasy** here. – Cheers and hth. - Alf Oct 29 '12 at 15:52
  • @JamesKanze `#pragma once` works for me in g++ 4.7. Did you see the portability list on wikipedia? – Seth Carnegie Oct 29 '12 at 15:54
  • @Alf I'm afraid I'm speaking from experience; remote mounts (especially the way Purify handles them) make it totally impossible to implement a 100% reliable `#pragma once`. The OS doesn't know that two different mounted file systems refer to the same underlying system, but with different names. All the OS sees (at the most) is the IP address of the server. If the same file is served up from two different machines (which can easily happen), then every test you can run will show two different files. – James Kanze Oct 29 '12 at 15:57
  • @James: your statement is incorrect. it is true that with remote file systems one can do things that foul up #pragma once, and it is also true that just with local file systems one can do things that foul up ordinary header guards. to the degree that that is an argument about #pragma once, it favors #pragma once (it is indeed the main reason why some people prefer #pragma once), and not, as your statement erroneously seemed to indicate, the opposite. – Cheers and hth. - Alf Oct 29 '12 at 15:59
  • @Alf I happen to have a copy (several, in fact) of g++ handy to check. I explained why I thought the way I did. The documentation makes no mention of `#pragma once` (although it describes a number of other pragmas). – James Kanze Oct 29 '12 at 16:04
  • @JamesKanze yes it does: http://gcc.gnu.org/onlinedocs/gcc-4.6.2/cpp/Alternatives-to-Wrapper-_0023ifndef.html mentions `#pragma once` – Seth Carnegie Oct 29 '12 at 16:06
  • @Alf My statement is based on actual experience. With remote mounted file systems, it is _impossible_ for the compiler to reliably know whether two paths refer to the same file or not. The information is simply not present. Where as a well chosen include guard is almost 100% reliable. – James Kanze Oct 29 '12 at 16:07
  • @James: your statement is incorrect. it is true that with remote file systems one can do things that foul up #pragma once, and it is also true that just with local file systems one can do things that foul up ordinary header guards. to the degree that that is an argument about #pragma once, it favors #pragma once (it is indeed the main reason why some people prefer #pragma once), and not, as your statement erroneously seemed to indicate, the opposite. – Cheers and hth. - Alf Oct 29 '12 at 16:10
  • @SethCarnegie I wouldn't trust Wikipedia for this. I'm trying to download the sources to g++ (they're big), to verify. In the past, it did _not_ work. And of course, it can't work if the files aren't mounted locally, because the information simply isn't available. – James Kanze Oct 29 '12 at 16:14
  • @JamesKanze that's not Wikipedia, that's the GCC website. – Seth Carnegie Oct 29 '12 at 16:25
1

You can use #pragma once in header file but it's not portable as #ifndef

Denis Ermolin
  • 5,530
  • 6
  • 27
  • 44
  • In fact, there's no system where `#pragma once` works reliably. – James Kanze Oct 29 '12 at 14:57
  • @James: you're wrong. in particular, it works reliably with g++ and visual c++. again, you might benefit from reading up on the wikipedia article. there is an [SO thread](http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard) about it but while it does get some pertinent facts on the table, it suffers from the usual SO lack of support for debate. so, arguments are generally not substantiated with examples, and many arguments are just assertive opinions (like the one you presented here). – Cheers and hth. - Alf Oct 29 '12 at 15:31
  • @Alf It doesn't work with g++, at least not under Linux or Solaris. I've seen it fail. And according to people who've experimented it with VC++ under Windows, it has the same problems there. In real life, on large projects, files are accessible from several different paths (due to things like automount), and the system sees them as completely different files. (I can clearly remenber a colleague doing an `rm -r` on a directory in `/tmp`, and losing his entire home directory.) Most of the time, such directories don't contain C++ headers, but they can. – James Kanze Oct 29 '12 at 16:13
  • @James: Provide a complete but minimal example exhibiting the behavior that you're referring to in the "it doesn't work", and file a bug report. Or the "It doesn't work" didn't happen, much like your pure fantasy statement about g++ ignoring `#pragma once`. The rest, talking about doing beginner's mistakes to screw up things for the feature you don't like, I find that unconvincing. – Cheers and hth. - Alf Oct 29 '12 at 16:21
  • @Alf The "it doesn't work" has happened, more than once, but I don't have access to the hardware necessary to reproduce it currently. G++ has evolved to treat `#pragma once` like VC++ (which wasn't the case in the past---at one point in the distant past, `#pragma once` would cause the compiler to start a computer game). And most compilers still don't support it. (The compiler I've used the most, Sun CC doesn't.) It would be very foolish to count on it. – James Kanze Nov 01 '12 at 17:25
0

Use #pragma once in your header file.

Sely Lychee
  • 312
  • 1
  • 9
  • This answer adds absolutely nothing that wasn't said five years ago. – user4581301 Mar 18 '17 at 00:22
  • Added this answer in another stackoverflow question, which was a duplicate of this one, it seems they redirected and displayed my answer here. Or i might not have seen other answers. – Sely Lychee Mar 18 '17 at 04:26