Class not declared in scope, but was included (and other errors)

As an experienced PHP and Java developer, I decided to learn C++. After a few weeks toying around, I decided to port a small game to C++ for the iPod/iPhone/iPad. After writing lots of code last few days, I decided to compile my code to test it, resulting in over 100 compile errors. Although I could fix most of them, I couldn't fix them all, including:

Level.h:26:0: "Block" was not declared in this scope in Level.h: (3 times, same line, same character) I think this one is pretty strange. I include Block.h in Level.h... Block.h compiles without any errors, and Level.h complains about the class Block not being declared, even though I just included that file.

Relevant code:

Block.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef BLOCK_H
#define BLOCK_H

#include "Level.h"
#include "Vertex2D.cpp"

class Block: public Vertex2D<LevelGridUnit>
{
public:
	Block(LevelGridUnit x, LevelGridUnit y);
};

#endif 


Level.h:
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
#ifndef LEVEL_H
#define LEVEL_H

typedef unsigned short LevelGridUnit;

#include "Tickable.h"
#include "Coordinate2D.cpp"
#include "Vertex2D.cpp"
#include "Block.h"

#include <vector>
#include <string>

class Level: public Tickable
{
protected:
	std::vector<Block *> blocks;
	std::string message;
	Vertex2D<LevelGridUnit> size;
public:
	Level(LevelGridUnit width, LevelGridUnit height);
	virtual void tick();
	Block * getBlockAt(Coordinate2D<LevelGridUnit> & coord);
	std::string getMessage();
	Vertex2D<LevelGridUnit> getSize();
	
	friend class LevelFactory;
};

#endif 


LevelLoader.cpp:16:0: Invalid conversion from "void*" to "std::istream*" in LevelLoader.cpp: No comment... just weird. No idea what the origin of this error is.

Relevant code:

LevelLoader.h, line 34
Full source: http://kutcomputers.nl/wwcode/LevelLoader.h
std::streamoff levelInputStreamDataOffset;

LevelLoader.cpp (stripped for readability, starting at line 12)
Full source: http://kutcomputers.nl/wwcode/LevelLoader.cpp
1
2
3
4
5
6
LevelLoader::LevelLoader(std::istream & levelInputStream):
	factory(),
	levelId(0),
	levelInputStream(levelInputStream),
	levelInputStreamDataOffset(levelInputStream.tellg())
{}


LevelLoader.cpp:29:0: invalid operands of types "std::istream*" and "LevelId" to binary 'operator>>': Documentation tells me you can use the >> operator of istream to "read" data from files. Why isn't this working?
Docs from C++.com: http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/

Relevant code:

LevelLoader.h, line 19:
Full source: http://kutcomputers.nl/wwcode/LevelLoader.h
typedef unsigned short LevelId;

LevelLoader.cpp, starting from line 28:
Full source: http://kutcomputers.nl/wwcode/LevelLoader.cpp
1
2
LevelId levelCount;
this->levelInputStream >> levelCount;


...and some other errors, but I assume the other errors are the results of the errors above.

Screenshot of compile errors (I don't know how to copy/paste them from Xcode)
http://www.plaatjesupload.nl/bekijk/2010/09/12/1284320549-210.png

Full sourcecode:
http://kutcomputers.nl/wwcode/

Could someone explain me those errors?

Other suggestions/comments/feedback is also welcome.
Last edited on
I'm a bit pressed for time, but I can explain the last error quickly. You need to overload >> so that your program knows how to read from an istream object into your LevelId object. >>'s usually seen behavior has already been defined for integers, C-strings, chars, and most basic types, as well as for boolean shifting (its original function), but not for custom objects.

For the error above that, the code at line 4 looks a bit suspicious... what are you trying to do there?

-Albatorss
Last edited on
"You need to overload >> so that your program knows how to read from an istream object into your LevelId object."

I just want to read the bytes from the stream and read them in the variable. Besides, LevelId is just a typedef of an unsigned short; just to serialize and deserialize it. If my way isn't the right way, which is? *consults google while waiting for answer*

"For the error above that, the code at line 4 looks a bit suspicious... what are you trying to do there?"

I'm initiating private member-variable "levelInputStream" with a reference to the first argument "levelInputStream", which has the same name, obviously.

LevelLoader.h:
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
#ifndef LEVELLOADER_H
#define LEVELLOADER_H

#include "LevelFactory.h"
#include "Level.h"

#include <iostream>
#include <fstream>

typedef unsigned short LevelId;
enum BlockType { BLOCK, BOX, TARGET };
const int LEVEL_ID_EXCEEDS_LEVEL_COUNT = 1;

// A class capable of loading a level from an inputstream. The level is loaded
// once and multiple instances can be created without reloading.
class LevelLoader
{
	// The current level-id.
	LevelId levelId;
	
	// The Level-inputstream.
	std::istream * levelInputStream;
	
	// The Level-inputstream starting-position pointer.
	std::streamoff levelInputStreamDataOffset;
	
	// The level-factory used to re-create the levels multiple times.
	LevelFactory factory;
	
public:
	~LevelLoader();
	
	//Construct a new Level-loader.
	LevelLoader(std::istream & levelInputStream);
	
	// Load a new level by ID.
	void prepareLevel(LevelId levelId);
	
	// Get the last loaded level by creating a new Level instance.
	Level makeLevel();
};

#endif 


Although the names are equal, a name conflict is not the problem, for renaming the first argument does not solve any error. Also, the compiler complains about the 5th line, not the 4th:
levelInputStreamDataOffset(levelInputStream.tellg())
Last edited on
shameless bump
I noticed that in a couple of headers you include source files. You shouldn't be doing this. Maybe it was just a typo, you wrote ".cpp" instead of ".h", I'm just saying in case you didn't notice.

your compiler wrote:
LevelLoader.cpp:29:0: invalid operands of types "std::istream*" and "LevelId" to binary 'operator>>'

It complains because you try to use a std::istream pointer instead of a std::istream object. You should do it like this:

1
2
LevelId levelCount;
*(this->levelInputStream) >> levelCount;

Another thing:

1
2
3
4
5
6
7
8
9
10
LevelLoader::LevelLoader(std::istream & levelInputStream):
	factory(),
	levelId(0),

        //you should store the address of the parameter
        //in your member pointer
	levelInputStream(&levelInputStream),
 
	levelInputStreamDataOffset(levelInputStream.tellg())
{}

As for the first error, I'm not sure. Maybe it has to do with including source files. Fix that and see if the error persists. Also, I think it's a good idea to check your dependencies again. For example, I don't see why it's necessary to include level.h in block.h
Last edited on
Thanks :D

All compile errors are gone.

Though, the .cpp files you're talking about aren't really sourcefiles. They're template classes. You can't separate template into .h and .cpp for some reason, so I put the sourcecode in a single file and named it .cpp.

C++ docs explaining about template classes, tells me you can't separate the source in a header and a source file, but it doesn't tell me what the file should be named:
> http://www.cplusplus.com/doc/tutorial/templates/

Coordinate2D.cpp:
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
#ifndef COORDINATE2D_CPP
#define COORDINATE2D_CPP

/** An abstract class representing a 2D coordination. */
template<class T>
class Coordinate2D
{
public:
	virtual T getX() const = 0;
	virtual T getY() const = 0;
	
	bool operator==(Coordinate2D<T>& coord) const
	{
		return this->getX() == coord.getX()
			&& this->getY() == coord.getY();
	}
	
	bool operator!=(Coordinate2D<T>& coord) const
	{
		return this->getX() != coord.getX()
			|| this->getY() != coord.getY();
	}
	
	~Coordinate2D(){}
};

#endif 


Should this be named .h or .cpp?
I assumed .cpp, but after some google'ing while writing this, I found this text:
> http://www.iis.sinica.edu.tw/~kathy/vcstl/templates.htm

This tutorial suggests storing it in a .h file, not a .cpp file.

Thanks again :D

edit:
Renaming the files .h generated warnings. Renamed them back to .cpp again.

warning: no rule to process file '$(PROJECT_DIR)/Classes/Coordinate2D.h' of type sourcecode.c.h for architecture i386
Last edited on
gamebuster wrote:
Though, the .cpp files you're talking about aren't really sourcefiles. They're template classes. You can't separate template into .h and .cpp for some reason, so I put the sourcecode in a single file and named it .cpp.

Ah, yes, templates should be put in header files. Also, make sure you don't try to compile these headers (I don't think just renaming them from "*.cpp" to "*.h" will work, maybe you'll have to change some project settings too), IINM that's what the last warning is about (you try to compile headers).
Last edited on
"(I don't think just renaming them from "*.cpp" to "*.h" will work, maybe you'll have to change some project settings too), IINM that's what the last warning is about (you try to compile headers)."

You're right. Unchecking "target" for those files in the files-browser did the trick. (renamed them to .h again...)

Tnx :D
Last edited on
Topic archived. No new replies allowed.