Well, the error message does make sense. That's what error messages are for: Making sense of mistakes. An error message that doesn't make sense wouldn't be added to the compiler. Compiler messages always
make sense, but I can't always make sense
of them. See? I'm shifting the blame from the perfectly working compiler, to my own lack of understanding - semantics, yes, but an important distinction none the less, otherwise I'll mentally assume the compiler is broken and ignore the good information it's trying to communicate to me.
I use a different compiler than yours, and my compiler gives different messages, so I also have no idea what that error message means.
So instead of guessing at what the error might be, knowing that the compiler already told me what the error is, I just now
researched how to read it.
Your error message:
c:\users om\documents\visual studio 2010\projects\pong\ball.h(12): error C2061: syntax error : identifier 'Paddle'
Is saying:
In the file, "
c:\users om\documents\visual studio 2010\projects\pong\ball.h"
At line number "
(12)"
We got an error code "
C2061"
Involving the identifier "
Paddle".
Everything there is perfectly understandable, except that we don't know what C2061 means. That's what the
research was for.
Top link of Google, without even having to follow the link, says: "
The compiler found an identifier where it wasn't expected. Make sure that identifier is declared before you use it."
So in the file
ball.h on
line 12, it found '
Paddle' but '
Paddle' wasn't yet declared.
Looking at the code you posted, at (around-ish) line 12 in ball.h, I find:
void Test_For_Collision(sf::FloatRect LeftWall, sf::FloatRect RightWall, Paddle &TopPaddle, Paddle &BottomPaddle);
And sure enough, Paddle is used there.
And that's how you read an error message. It tells us
what problem the compiler encountered, and
where it encountered it. Now the "
why" it encountered it is left to us.
Why does it not know what 'Paddle' is?
Why does it think it's not yet declared?
Ball.h quite clearly #includes "Paddle.h", so why is there a problem? And Paddle.h quite clearly includes "Ball.h", so why is there a problem?
Wait a sec... Ball.h includes Paddle.h that includes Ball.h that includes Paddle.h that includes Ball.h that includes Paddle.h that includes... Looks like an infinite #include loop to me. Good thing you have" #pragma once" there, keeping the header from being included more than one time.
But, oh wait, let's walk through this in our head real quick:
Let's say, Paddle.h gets included before Ball.h. It'll look like this:
Process Paddle.h
Include Ball.h
Don't include Paddle.h, because it was already included once.
But Ball.h needs Paddle!
But Paddle isn't defined, because it wasn't included because it was already included previously!
So when the compiler is compiling Ball.h, and encounters 'Paddle', it doesn't know what it is, because the header you included, you also told it not to include if it was already included... and it was already included, but someplace where Ball.h can't access it.
#include just means "Copy and paste the code from the file I'm including into this file."
So let's see what that might look like to the compiler:
//--------------------------------------------------
//Beginning of Paddle.h
#pragma once //Compiler: Activated! Got it! As a compiler, I won't include Paddle.h anymore.
#include <SFML/Graphics.hpp>
//--------------------------------------------------
//Beginning of SFML/Graphics.hpp
#pragma once //Compiler: Activated! Got it! As a compiler, I won't include SFML/Graphics.hpp anymore.
//Lots of SFML stuff here.
//End of SFML/Graphics.hpp
//--------------------------------------------------
#include "Ball.h"
//--------------------------------------------------
//Beginning of Ball.h
#pragma once //Compiler: Activated! Got it! As a compiler, I won't include Ball.h anymore.
#include <SFML/Graphics.hpp>
//--------------------------------------------------
//Compiler: Hey! We already included SFML/Graphics.hpp! We won't include it a second time.
//(Luckily, our copy+paste puts the SFML stuff ABOVE this stuff, so we still have access to it all)
//--------------------------------------------------
#include "Paddle.h"
//--------------------------------------------------
//Compiler: Hey! We already included Paddle.h! We won't include it a second time.
//(But our Paddle class is BENEATH us, so class Ball doesn't yet know it exists)
//--------------------------------------------------
class Ball
{
public:
Ball(float speedx, float speedy, sf::Image &BallImage);
void Update(sf::RenderWindow &Window);
void Draw(sf::RenderWindow &Window);
sf::FloatRect GetCollision();
//--------------------------------------------------
//Hey! What in the world is 'Paddle'? Going from top to bottom of this file I'm compiling,
//I don't see any 'Paddle' being declared before this line, so I don't yet know what a Paddle is.
//Error! Error! This type of error is "C2061".
//This file is "Ball.h"
//This line is "12"
//The variable I don't know is called "Paddle".
//--------------------------------------------------
void Test_For_Collision(sf::FloatRect LeftWall, sf::FloatRect RightWall, Paddle &TopPaddle, Paddle &BottomPaddle);
private:
sf::FloatRect Collision;
sf::Sprite BallSprite;
sf::Image BallImage;
float speedx, speedy;
};
//End of Ball.h
//--------------------------------------------------
class Paddle
{
public:
Paddle(float speedx, bool isplayercontrolled, sf::Image &Image);
void Draw(sf::RenderWindow &Window);
void Update(sf::RenderWindow &Window, Ball bally);
sf::FloatRect GetCollision();
private:
sf::Image PaddleImage;
sf::FloatRect Collision;
sf::Sprite PaddleSprite;
bool HasAI;
float speedx;
};
//End of Paddle.h
//--------------------------------------------------
Your Paddle class depends on the Ball class which depends on the Paddle class. This is known as a
circular dependency.
Circular dependcy isn't bad, but to make sure Ball knows about Paddle and Paddle knows about Ball, you can't
define (give the details of) the same class twice - that's a compiler error.
But also, both classes need to know about the other, otherwise there's a compiler error.
So what you do is
declare the class (which means, say that the class exists) without yet
defining what the class is.
You: I
declare that there is a class called "Paddle"
You: I
declare that there is a class called "Ball" and I
define that it has such and such variables and functions, including ones that use the previously
declared Paddle, which Ball knows exists but which hasn't yet
defined.
You: I now
define "Paddle", and the functions and variables it has, including that it needs "Ball" (which is already
defined and declared).
Declaring something without yet defining it, is called a "
forward declaration". We also call this a "pre-declaration".
You can forward declare functions and variable types. In this case, we're forward declaring a class, so it's a "
forward class declaration".
It looks like this:
class Paddle; //Declared without being defined.
So when the compiler "copy + pastes" your headers together, the end result should look roughly like this:
//Just (pre)declare the "Paddle" class.
class Paddle;
//Declare AND define the Ball class.
class Ball
{
//Uses 'Paddle'... Great! I know that Paddle exists, though I don't yet know what it is.
}
//Define the pre-declared Paddle.
class Paddle
{
//Uses 'Ball'. Great! I know that Ball exists, AND I know what it is.
}