2

I am currently programming a program which searches song according to diffrent parameters. In my system there are 2 types of songs: lyric and instrumetal. Since i need to put both of them in 1 vector, I have a song class and a LyricsSong & InstrumentalSong subclasses.

So I there is a Song.h file:

#include <stdio.h>
#include <iostream>
#include <string>


class Song
{
public:
    std::string title;
    virtual void print();
    virtual void printSong(std::string query);
};

and there are the instrumental and lyrics subclasses, which are defined this way:

class LyricsSong : public Song
class InstrumentalSong : public Song

both of the include Song.h, and in both of them the class is defines only in the header file.

when I try to run another file which use the both subclasses, and includes:

#include "LyricsSong.h"
#include "InstrumentalSong.h"

(and obviously more cpp libraries), i get the following compilation error:

In file included from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/InstrumentalSong.h:16:0,
                 from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/songsParser.cpp:26:
/cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/Song.h:6:7: error: redefinition of 'class Song'
 class Song
       ^
In file included from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/LyricsSong.h:15:0,
                 from /cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/songsParser.cpp:25:
/cygdrive/c/Users/Username/Documents/C++ Workshop/ex2/ex2_code/Song.h:6:7: error: previous definition of 'class Song'
 class Song
       ^

when:

  • lines InstrumentalSong.h:16:0 and LyricsSong.h:15:0 are where i include "Song.h"
  • lines songsParser.cpp:25 and songsParser.cpp:26 are where i include InstrumentalSong.h and LyricsSong.h
  • line Song.h:6:7: is the defination of Song.h (where it's say's class Song, as showed above).

What should I do? P.S. I do not import any cpp file ever, only header files.

3 Answers3

13

You have to tell preprocessor to include your header files only once. You can achieve by adding #pragma once on the top of all *.h files:

#pragma once

//Your header file's code

It is also a good practice to always begin header files with this line.

psliwa
  • 1,094
  • 5
  • 9
  • 1
    `#pragma once` is not standard, and it can not work in some situations. It was explicitly not standardized because of those (not portably solvable) problems. [See here](http://stackoverflow.com/questions/787533/is-pragma-once-a-safe-include-guard/1946730#1946730) for some issues. – Fabio Fracassi Sep 03 '15 at 15:57
  • But it actually solved my problem. I spent around an hour searching for a solution and this^ solved it. But why does it have that one drawback? – Prolight Jun 09 '20 at 23:02
5

They both include 'Song.h' file and preprocessor takes the file content twice. You need to write 'LyricsSong.h' and 'InstrumentalSong.h' file contents inside #ifndef #define and #endif directives. Like this

#ifndef LYRICS_SONG_H
#define LYRICS_SONG_H

your code goes here.
...

#endif 
Ashot Khachatryan
  • 2,156
  • 2
  • 14
  • 30
  • 1
    In most compilers you can use more efficent #pragma once also – DawidPi Sep 03 '15 at 13:54
  • 2
    @DawidPi I don't like to use tools/features which is non-standard and don't suggest anyone to do so. – Ashot Khachatryan Sep 03 '15 at 14:03
  • Most importantly, he needs to put an include guard into `Song.h`. Putting it into `LyricsSong.h` and `InstrumentalSong.h` is good practice, but not enough. – ex-bart Sep 03 '15 at 14:04
  • I uderstand this in fact, I also prefer standard solutions but #pragma once is available in every modern compiler. msvs,gcc,clang or whatever. And if you have lot's of files it can reduce compile time significantly – DawidPi Sep 03 '15 at 14:05
  • 1
    At least for gcc `#pragma once` is probably no more efficient than the standard include guards, see [here](https://gcc.gnu.org/onlinedocs/gcc-4.4.0/cpp/Once_002dOnly-Headers.html#Once_002dOnly-Headers). Other compilers probably have similar optimizations. – ex-bart Sep 03 '15 at 14:07
1

As already answered, I would also use #pragma once, it is more convenient and clean. But be aware that it is not a C++ standard, so it can be a problem if you have to use different compilers (although it is a wide-spread extension).

fbastian
  • 111
  • 4