2

Ok, so I'm a HTML/Javascript/PHP professional, but I'm trying to learn C++. I'm still a newbie at it, and I have a C++ programming project that I have errors with.

The file that contains int main() is 'football.cpp', and I have .h and .cpp files for three classes that I have to use: Game, Team, and Date. Each instance of Team contains a vector of Games, and each Game contains a Date. Date does not contain instances of any other class.

I am trying to find a way to use #include and #ifndef statements at the tops of the files so that I don't get errors when I compile, but I haven't found a combination that works. I am not sure if there are other bugs. Here's my current #include sections, not counting other libraries:

football.cpp

#include "game.h"
#include "team.h"
#include "date.h"

team.h

#ifndef __game_h_
#define __game_h_
#endif

team.cpp

#include "team.h"
#ifndef __game_h_
#define __game_h_
#endif

game.h

#ifndef __date_h_
#define __date_h_
#endif

game.cpp

#include "game.h"
#ifndef __date_h_
#define __date_h_
#endif

date.cpp

#include "date.h"

I use Cygwin g++ compiler, and the line I use to compile it is:

g++ football.cpp team.cpp game.cpp date.cpp -o football.exe

Here are all the errors I get: (WARNING, WALL OF TEXT)

$ g++ football.cpp team.cpp game.cpp date.cpp -o football.exe

In file included from football.cpp:9:0:
game.h:15:96: error: ‘Date’ has not been declared
game.h:24:1: error: ‘Date’ does not name a type
game.h:37:1: error: ‘Date’ does not name a type
football.cpp: In function ‘int main(int, char*)’:
football.cpp:65:70: error: no matching function for call to ‘Game::Game(std::string&, std::string&, int [5], int [5], Date&)’
game.h:15:1: note: candidates are: Game::Game(std::string, std::string, const int, const int*, int)
game.h:14:1: note: Game::Game()
game.h:10:12: note: Game::Game(const Game&)
In file included from team.cpp:4:0:
team.h:24:8: error: ‘Game’ was not declared in this scope
team.h:24:12: error: template argument 1 is invalid
team.h:24:12: error: template argument 2 is invalid
team.cpp: In member function ‘float Team::getStat3()’:
team.cpp:36:26: error: request for member ‘size’ in ‘((Team*)this)->Team::games’, which is of non-class type ‘int’
team.cpp:37:21: error: invalid types ‘int[int]’ for array subscript
team.cpp:37:50: error: invalid types ‘int[int]’ for array subscript
team.cpp:38:21: error: invalid types ‘int[int]’ for array subscript
team.cpp:38:47: error: invalid types ‘int[int]’ for array subscript
team.cpp:38:76: error: invalid types ‘int[int]’ for array subscript
team.cpp:38:106: error: invalid types ‘int[int]’ for array subscript
team.cpp: In function ‘bool compare2(Team, Team)’:
team.cpp:45:39: error: request for member ‘size’ in ‘t1.Team::games’, which is of non-class type ‘const int’
team.cpp:46:39: error: request for member ‘size’ in ‘t2.Team::games’, which is of non-class type ‘const int’
team.cpp:50:17: error: request for member ‘size’ in ‘t1.Team::games’, which is of non-class type ‘const int’
team.cpp:50:35: error: request for member ‘size’ in ‘t2.Team::games’, which is of non-class type ‘const int’
team.cpp:52:24: error: request for member ‘size’ in ‘t1.Team::games’, which is of non-class type ‘const int’
team.cpp:52:43: error: request for member ‘size’ in ‘t2.Team::games’, which is of non-class type ‘const int’
team.cpp: In function ‘bool compare3(Team, Team)’:
team.cpp:62:29: error: passing ‘const Team’ as ‘this’ argument of ‘float Team::getStat3()’ discards qualifiers
team.cpp:63:29: error: passing ‘const Team’ as ‘this’ argument of ‘float Team::getStat3()’ discards qualifiers
In file included from game.cpp:5:0:
game.h:15:96: error: ‘Date’ has not been declared
game.h:24:1: error: ‘Date’ does not name a type
game.h:37:1: error: ‘Date’ does not name a type
game.cpp: In constructor ‘Game::Game()’:
game.cpp:26:3: error: ‘date’ was not declared in this scope
game.cpp:26:15: error: ‘Date’ was not declared in this scope
game.cpp: At global scope:
game.cpp:29:94: error: ‘Date’ has not been declared
game.cpp:29:1: error: prototype for ‘Game::Game(std::string, std::string, int*, int*, int)’ does not match any in class ‘Game’
game.h:10:12: error: candidates are: Game::Game(const Game&)
game.h:15:1: error: Game::Game(std::string, std::string, const int*, const int*, int)
game.cpp:13:1: error: Game::Game()
game.cpp: In member function ‘int Game::getVisitingScore(int) const’:
game.cpp:80:10: error: ‘visitingScores’ was not declared in this scope
game.cpp: At global scope:
game.cpp:94:1: error: ‘Date’ does not name a type


Will edit if further clarification is needed, although I don't think it will be.

Any help would be vastly appreciated.

slybloty
  • 6,346
  • 6
  • 49
  • 70
CalvinCopyright
  • 165
  • 2
  • 4
  • 10
  • Just so you know, a double underscore is reserved in any scope, and starting with an underscore is reserved in the global scope (whereas putting a capital letter after that first underscore is reserved in any scope). – chris Sep 13 '12 at 15:17
  • Don't use names that start with (or contain) two underscores (or that start with with one underscore followed by a capital letter). They're reserved for the implementation. This has nothing to do with the problem, though. – Pete Becker Sep 13 '12 at 15:17
  • @PeteBecker, It took me 100 times of reading the answer to notice, but the double underscores don't have to be at the beginning for it to violate the rule. – chris Sep 13 '12 at 15:18
  • @chris - you're right, two consecutive underscores anywhere in a name makes it reserved. Fixed. – Pete Becker Sep 13 '12 at 15:20
  • These errors are impossible to analyze, apparently because the files you've shown are incomplete. Yes, the include guards are messed up, but it's impossible to say what's really going on without seeing more of the code. Start with something simpler: a single .h file and a corresponding .cpp file, and get that combination working. If you run into problems, cut the files down as much as you can and still see the problem, and then post them here. – Pete Becker Sep 13 '12 at 15:23
  • 1
    For anyone who's wondering where the reserved identifier talk is coming from, see [this question](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – chris Sep 13 '12 at 15:25

4 Answers4

8

I think that you're misunderstanding the use of include guards.

#ifndef __game_h_
#define __game_h_
// ...
#endif

The set of statements above would typically be used only in the header file describing your game interface, to prevent multiple-inclusion of that header file.

But in your code, you've added include guards to header and implementation, and also you seem to be confusing entities - unless I'm misunderstanding your file contents - for instance in team.h, you have what appear to be include guards for game.

My guess is that your misuse of include guards is actually preventing some types from being defined at all.

As others have mentioned, don't use names beginning with double underscores.

As an example, add include guards to your team header to prevent multiple-inclusion of that file, and give the include guards a name that reflects the module that they're guarding:

// team.h
#ifndef TEAM_H
#define TEAM_H

// ... code for team.h in here

#endif    // TEAM_H
pb2q
  • 58,613
  • 19
  • 146
  • 147
  • `_TEAM_H_` is also reserved, as it begins with an underscore and a capital. There's really no need to sprinkle underscores around like this; how about just `TEAM_H`? – Mike Seymour Sep 13 '12 at 15:30
  • Worth mentioning that each implementation file is compiled seperately, and the include guards only prevent multiple inclusion within a single compilation. We must get one question a week from a newbie who thinks that include guards prevent multiple inclusions across all compilations. – john Sep 13 '12 at 15:37
  • Thank you so much! So, just to make things clear, the #ifndef-#endif encloses all other code, should only be used in .h files, and should define the file name, as team.h -> TEAM_H . After that, #include statements can be used liberally in .cpp files. Man, C++ can be frustrating. – CalvinCopyright Sep 13 '12 at 15:42
2

It looks like you have 2 problems here: The first is that you are using include guards in your source files; the second is that the order in which you have included your files is wrong.

First, include guards. Others have answered this question already, so I'll be brief. Include guards are used only in header files in order to prevent classes/types being declared more than once. For example if I had:

"game.h":

class Game {};

"game.cpp":

#include "game.h"
#include "game.h"  // ERROR:  class Game is declared twice.

To fix this I would use include guards in "game.h":

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

class Game {};

#endif

The first time the file is included, GAME_H_INCLUDED is not defined, so Game is declared. The second time it is include, GAME_H_INCLUDED is defined, so the declaration is skipped.

The problem you have is that your include guards in you source files will cause all of the implementation to be skipped:

broken "game.cpp":

#include "game.h"
#ifndef GAME_H_INCLUDED  //  This is defined in "game.h" so everything will be
                         //  skipped until #endif is encountered.
#define GAME_H_INCLUDED

//  Implementation of Game class

#endif

Second, the order in which you are including headers is incorrect. I'm guessing you have something like this:

"game.h"

#ifndef GAME
#define GAME

class Game
{
    Date mDate;  // Member of type Date, declared in "date.h"
};

#endif

"date.h"

#ifndef GAME
#define GAME

class Date
{
};

#endif

"game.cpp"

#include "game.h"  // ERROR:  Game relies on the Date class,
                   //         which isn't included yet
#include "date.h"

To fix this either swap the order of the includes in "game.cpp":

"game.cpp"

#include "date.h"
#include "game.h"  // Fine, we know what a Date is now.

Or include "date.h" in "game.h":

"game.h"

#include "date.h"
#ifndef GAME
#define GAME

class Game
{
    Date mDate;  // Member of type Date, declared in "date.h"
};

#endif

"game.cpp"

#include "game.h"  // Still fine, "date.h" is included by "game.h"
Bok McDonagh
  • 1,367
  • 10
  • 27
0

you don't need the guards in your c++ files

Minion91
  • 1,911
  • 12
  • 19
0

The error is that you should use include guards only in your header files

If you have a

BaseClass.h
struct HumanEntity { }

and then have different classes use that base class, without the include guard you may run into issues. That is why you put a

#ifndef __MYGUARD
#define __MYGUARD

... // here is your header code

#endif
SinisterMJ
  • 3,425
  • 2
  • 33
  • 53