Please Help Me Find The Bugs

Started by
13 comments, last by Odion 7 years, 8 months ago

Hi all,

I am writing a little 2D battle simulator for practice.

movement (w,a,s,d)

put soldiers for the two different armies (1,2)

start battle (enter)

But I cant run it, and I just cant seem to find the problem with my code.

I am beginner, so probably I am doing something really stupid, which shouldn't be done, but even after researching the error codes, couldn't come up with anything.

Some help would be much appreciated.

My zipped project folder is added to attachments. (Visual Studio)

Thank you.

Advertisement

What do you mean you can't run it?

Does it fail to compile or link?

Does it compile and link correctly, but crash on start-up or at any other specific time?

You mentioned error codes -- what are they? Don't make us work for things you can easily provide.

Hello to all my stalkers.

I am sorry.

It fails to compile. Spent hours trying to figure out the problem. The errors I am getting are not there, they seem like phantoms errors caused by something else. I am guessing I am using pointers wrong and that somehow affects everything, but its just a hunch.

Screenshot_15.png

Post mapmanager.h

You can put code in the code tags (the symbol in the text editor that looks like <> )

Hello to all my stalkers.


#pragma once
#include <string>
#include <vector>
#include "Soldier.h"

using namespace std;

class MapManager
{
public:
	MapManager();
	~MapManager();

	int loadMap(string mapName);
	int placeArmies();
	int printMap();
	int battle();
	Soldier* getClosestEnemy(Soldier* soldier, char self_owner);
	void setTile(int x, int y, char c);
	char getTile(int x, int y);
	void resetTile(int x, int y);

private:
	vector <Soldier *> soldiers;
	vector <vector<char>> _mapData;
	vector <vector<char>> _origMapData;
	int cursorX = -1;
	int cursorY = -1;
	string _path = "Data\\Maps\\";
};


Seems alright on its own. However, looking more closely at your error messages it seems like Soldier has a pointer to MapManager, and MapManager has a pointer to Soldier.

This is most likely causing a circular reference (to know what a MapManager is, you need to know what a Soldier is, which needs to know what a MapManager is, etc).

Since you're only using pointers (at least in MapManager), you can forward declare the Soldier class inside MapManager.h. This basically says "somewhere, there is a class called Soldier. You don't need to worry about the details here, because all we currently want is to have a pointer to it".

Before class MapManager, add


class Soldier;

In MapManager.cpp you will need to include the Solider.h file to get the proper contents available to you.

Also of note, I would recommend not putting "using namespace std;" in a header. This can cause namespace pollution -- every file that includes MapManager will now suddenly also inherit the using declaration.

If you need to use using declarations, it's best to put them locally -- in the .cpp file.

Hello to all my stalkers.

Thank you. That was the problem....It would have took me days to find it. I also had to put


class MapManager;

in Soldier.h


I took out "using namespace std;" from the headers as well. Thank you for the advice.

I don't understand "Since you're only using pointers.." though. It would be different if I didn't use pointers?

It would be different if I didn't use pointers?

Let's say you add an instance of class Soldier to your class MapManager:


class MapManager
{
    Soldier mySoldier;
    int myMagicInt;
};

In order to know how large MapManager is (how much memory has to be set aside every time an instance of MapManager is created), we need to know all the details of Soldier. Does it just have an int for HP? Does it have 50 floats with all kinds of stats?

In this case, MapManager would need to know both that Soldier exists, and the details of it.

In the case where you have a pointer to it, all you need to know is that it exists (so it understands that "Soldier" is the name of a class and not just random letters). We still need to know how much memory to set aside for the pointer, however, since all pointers are the same size, it doesn't need to know the details of the class. If the class is huge or tiny, the pointer to it will remain the same size.

The reason why you still need to include Soldier.h in the MapManager.cpp file, is because now you're wanting to access the Soldier details -- mySoldier->someFunction().

To access those details, you need to know they exists, hence the reason for the include here.

This also means you can't have 2 classes which have instances of each other inside each other.

In this case, you would need to split things up somehow, so that either 1 class contains a pointer to the other, or to create a new class which contains both of them.

Hello to all my stalkers.

I get it. Mostly.

all you need to know is that it exists (so it understands that "Soldier" is the name of a class and not just random letters)


I don't really get why including "Soldier.h" does not provide this information tho'. Isn't including Soldier.h means that that the whole Soldier.h code gets copied into the current block of code?

I don't really get why including "Soldier.h" does not provide this information tho'. Isn't including Soldier.h means that that the whole Soldier.h code gets copied into the current block of code?


That's true, but remember that C++ translation units are compiled from top to bottom and the compiler doesn't know that a symbol exists until it reaches the point where it is declared. If MapManager references Soldier, then Soldier must have been declared (forward or otherwise) before MapManager is. If Soldier is declared after it, the compiler doesn't know it exists at the time that it compiles MapManager. If Soldier IS declared before MapManager, but the compiler can't compile Soldier's definition because it doesn't know what a MapManager is, then the compiler also won't know what a Soldier is when it compiles MapManager because it tried to compile Soldier and failed.

The same thing happens with functions and variables. The following code has the same problem:
void abc()
{
  // the compiler doesn't know what xyz is yet
  xyz();
}

void xyz()
{
  abc();
}
So here again we need a forward declaration:

void xyz();

void abc()
{
  // now the compiler knows that xyz is defined somewhere else, so this compiles
  xyz();
}

void xyz()
{
  abc();
}

This topic is closed to new replies.

Advertisement