Page 1 of 1

Class Dependency issues (C++)

Posted: Tue May 17, 2011 11:04 am
by ajtgarber
Language: C++
Compiler: GCC 4.4

I have a class NPC that contains an NPCBehavior* instance, the NPCBehavior class has a method update(NPC* npc). Both the classes are dependent on each other. I also have a DefaultNPCBehavior class that is used by the NPC class inside the constructor to give a default behavior to itself. DefaultNPCBehavior extends NPCBehavior. gcc is giving me the following message:
In file included from NPC.h:10,
from NPCBehavior.h:7:
DefaultNPCBehavior.h:10: error: expected class-name before ‘{’ token
NPC.h

Code: Select all

#ifndef NPC_H
#define NPC_H

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <iostream>
#include "Entity.h"
#include "AnimatedEntity.h"
#include "NPCBehavior.h"
#include "DefaultNPCBehavior.h"

class NPCBehavior;
class DefaultNPCBehavior;

class NPC : public AnimatedEntity {
	private:
		int mapShiftX, mapShiftY;
		NPCBehavior* behavior;
	public:
		NPC(SDL_Surface* surface, int x, int y, int width, int height);
		~NPC();

		int getMapShiftX();
		int getMapShiftY();
		void setMapShiftX(int mapShiftX);
		void setMapShiftY(int mapShiftY);

		void setNPCBehavior(NPCBehavior* behavior);

		void update(); //inherited from Entity, AnimatedEntity
		void render(SDL_Surface* screen); //inherited from Entity, AnimatedEntity
};

#endif
NPC.cpp

Code: Select all

#include "NPC.h"

using namespace std;

NPC::NPC(SDL_Surface* sheet, int x, int y, int width, int height) : AnimatedEntity(sheet, x, y, width, height), mapShiftX(0), mapShiftY(0) {
	behavior = new DefaultNPCBehavior();
	cout << behavior << endl;
}
NPC::~NPC() {
	//possible memory leak with behavior (WARNING)
}

void NPC::setNPCBehavior(NPCBehavior* behavior) {
	delete this->behavior;
	this->behavior = behavior;
}

int NPC::getMapShiftX() {
	return mapShiftX;
}
int NPC::getMapShiftY() {
	return mapShiftY;
}
void NPC::setMapShiftX(int mapShiftX) {
	this->mapShiftX = mapShiftX;
}
void NPC::setMapShiftY(int mapShiftY) {
	this->mapShiftY = mapShiftY;
}

void NPC::update() {
	AnimatedEntity::update();
	setX(getX()+getXVel());
	setY(getY()+getYVel());
	behavior->update(this);
}
//extremely similar to AnimatedEntity::render with the change being with the offset rectangle
void NPC::render(SDL_Surface* screen) {
	SDL_Rect offset;
	offset.x = getX()+mapShiftX;
	offset.y = getY()+mapShiftY;

	SDL_Rect clip;
	clip.x = getFrameNum()*getWidth();
	clip.y = getDirection()*getHeight();
	clip.w = getWidth();
	clip.h = getHeight();

	SDL_BlitSurface(getSheet(), &clip, screen, &offset);
}
NPCBehavior.h

Code: Select all

#ifndef NPCBEHAVIOR_H
#define NPCBEHAVIOR_H

#include <iostream>


#include "NPC.h"
#include "Entity.h"

class NPC;

class NPCBehavior {
	public:
		NPCBehavior();

		virtual void update(NPC* npc) = 0;
};

#endif
NPCBehavior.cpp

Code: Select all

#include "NPCBehavior.h"

NPCBehavior::NPCBehavior() {
	
}
DefaultNPCBehavior.h

Code: Select all

#ifndef DEFAULTNPCBEHAVIOR_H
#define DEFAULTNPCBEHAVIOR_H

#include "Entity.h"
#include "NPCBehavior.h"
#include "NPC.h"

class NPC;

class DefaultNPCBehavior : public NPCBehavior {
	private:
		int counter;
	public:
		DefaultNPCBehavior();

		void update(NPC* npc);
};

#endif
DefaultNPCBehavior.cpp

Code: Select all

#include "DefaultNPCBehavior.h"

DefaultNPCBehavior::DefaultNPCBehavior() : counter(0) {

}

void DefaultNPCBehavior::update(NPC* npc) {
	if(npc->getXVel() == 0) npc->setXVel(4);
	counter++;
	if(counter == (60*4)) {
		counter = 0;
		npc->setXVel(-npc->getXVel());
	}
}

Re: Class Dependency issues (C++)

Posted: Tue May 17, 2011 2:59 pm
by bnpph
It might be from DefaultNPCBehavior.h because you didn't forward declare class NPCBehavior.

Also, if you only need pointers in h file, then you can only include in the .cpp
like this:

bar.h

Code: Select all

#pragma once
class bar {
public:
  int var;
  bar();
  ~bar();
};
(pretend bar.cpp exists and implements everything)

foo.h

Code: Select all

#pragma once
class bar;
class foo {
  foo();
  ~foo();
  bar* m_bar;
};
foo.cpp

Code: Select all

#include "foo.h"
#include "bar.h"

foo::foo() {
  m_bar = new bar[4];
}

foo::~foo() {
  delete[] m_bar;
}

This gets rid of circular dependency, improves compile time, and is "proper" way to do so.

Re: Class Dependency issues (C++)

Posted: Wed May 18, 2011 10:16 am
by ajtgarber
If I compile it with the forward declaration of NPCBehavior in DefaultNPCBehavior I get these error messages:
In file included from NPC.h:10,
from NPCBehavior.h:7:
DefaultNPCBehavior.h:11: error: invalid use of incomplete type ‘struct NPCBehavior’
DefaultNPCBehavior.h:9: error: forward declaration of ‘struct NPCBehavior’

Re: Class Dependency issues (C++)

Posted: Wed May 18, 2011 8:06 pm
by ajtgarber
While I do see how that foo, bar class implementation gets rid of circular dependencies, I guess I don't really see how I can still implement what I need to with this.
The NPC object needs to have a way to call update on an NPCBehavior object. and the NPCBehavior object needs some way to tell what its updating so it can call
methods such as setXVel or something of that sort.

If I'm being an idiot feel free to tell me so.

I know I can use an Entity* instead of using an NPC* inside the NPCBehavior class, but if I don't have to I'd prefer not to, since the NPCBehavior class is meant to work on NPC's rather than generic entities.

Re: Class Dependency issues (C++)

Posted: Fri May 20, 2011 10:29 am
by MrDeathNote
In NPC.h your including AND forward declaring NPCBehavior.h and DefaultNPCBehavior.h. Remove the includes and put them in NPC.cpp. Also you cannot forward declare NPCBehavior in DefaultNPCBehavior.