Problem with classes [C++ question]

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
rimbou
Posts: 20
Joined: Fri Nov 24, 2006 12:09 pm

Problem with classes [C++ question]

Post by rimbou »

I'm not sure if this is the best place to ask this, but here it goes.

I have two classes and I want the first one to have a pointer to the second one and the second one to have a pointer to the first one...I get all sorts of compiling errors.

Here is a simplified version of it:

class1.h

Code: Select all

#ifndef _CLASS_1_H_
#define _CLASS_1_H_
#include "class2.h"
class class1
{
   class2 *p;
   void Example();
   ...
};
#endif
class1.cpp

Code: Select all

#include "class1.h"
void class1::Example()
{
   ...
}
Then the trouble starts here with the second class

class2.h

Code: Select all

#ifndef _CLASS_2_H_
#define _CLASS_2_H_
#include "class1.h"
class class2
{
   class1 *p;
   void Example();
   ...
};
#endif
class2.cpp

Code: Select all

#include "class2.h"
#include "class1.h"
void class2::Example()
{
   ...
}

I get all sort of errors like: "missing storage-class or type specifiers", "unexpected 'class class2 ('", "unexpected token(s) preceding '{'; skipping apparent function body", etc.

Any idea of how can I solve this?
Thanks in advance.
________
Thinkmill
Last edited by rimbou on Fri Feb 18, 2011 6:06 pm, edited 1 time in total.
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

First make sure, you really need this. Bidirectional dependencies are bothersome, and most of the time not needed.

You can do this with forward declarations:

Code: Select all

#ifndef _CLASS_1_H_
#define _CLASS_1_H_

// Forward declaration of class2, the compiler now knows that a class by
// this name exists, but doesn't know what it looks like.
class class2;

class class1
{
   class2 *p;
   void Example();
   ...
};
#endif 

Code: Select all

#include "class1.h"
// Include class2 header file after the class1 header.
// Because a forward declaration must appear before the class definition.
#include "class2.h"
void class1::Example()
{
   ...
} 
rimbou
Posts: 20
Joined: Fri Nov 24, 2006 12:09 pm

Post by rimbou »

Oh that was it! Thanks :)

Well I'm doing this because class1 is the main game class, and I want the other classes to have access to the main class (this is useful for example when you want the event reciever to move the camera, etc.). If anyone has an idea to do the same and avoid the bidirectional dependencies please tell me ;)

Thanks.
________
Suzuki boulevard s50
Last edited by rimbou on Fri Feb 18, 2011 6:06 pm, edited 1 time in total.
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

Indeed. A "main game class" should not be used by other classes at all, imho. In your example the camera is not moved by all the many things that are in your game class, but just by the event receiver. There is no main game class needed to be known in either camera or event receiver.

So instead of letting all classes get access to all other classes over the main game class, only let the classes access the specific subset of classes that they really need to operate on. In your example the event receiver needs the camera to move it. So make a public setCamera function in your event receiver, or make the camera a parameter of the event receiver constructor.

Low coupling - High cohesion. The fundamental rule in software engineering. Classes with a single, well defined, purpose that communicate with few other classes over a well defined interface. No catch-all-classes. These are much more difficult to extend and maintain over the course of development.
Halan
Posts: 447
Joined: Tue Oct 04, 2005 8:17 pm
Location: Germany, Freak City
Contact:

Post by Halan »

you could also make the main class the event receiver ;)
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

hmm. The classic implements ISwissArmyKnife.
Bad idea in general. Violates the high cohesion rule.
rimbou
Posts: 20
Joined: Fri Nov 24, 2006 12:09 pm

Post by rimbou »

Saturn wrote: So instead of letting all classes get access to all other classes over the main game class, only let the classes access the specific subset of classes that they really need to operate on. In your example the event receiver needs the camera to move it. So make a public setCamera function in your event receiver, or make the camera a parameter of the event receiver constructor.
I was doing that, it seemed like a good idea when you only had to pass the scenemanager and the driver but not now that it needs lots of things like camera, map, player, gamestate, etc classes...I don't know maybe I'll have to rethink the whole design.
________
LOLOL
Last edited by rimbou on Fri Feb 18, 2011 6:07 pm, edited 1 time in total.
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

greetings!

rimbou, know, i have the same situation. i'm developing my game, and right now i have my base game class, with many things in it. as for its private data, there i store pointers to:
1) IrrlichtDevice (no comments),
2) my bots container class (where i store all my monsters, it has in core::list<botMonsters*>)
3) my bot player, which is derived from my baseBot class
4) scene::ITerrainSceneNode (it will be used for creating the animators later)
5) scene::ITriangleSelector (i create this selector once there in baseGame class and later only use it, without many creations of the such selectors)

the idea of storing pointer to this base Game class is not the best solution on my opinion, and i tried to avoid this, but on this moment i didn't invent smth more suitable.

my baseBot class have to use createCollisionResponseAnimator, which is possible only from ISceneManager. so i'm getting to it over my baseGame* _pBaseGame pointer.

or for example in my baseBot's constructor i have to initialize its _timeForStand and _lastTimeOfTurn.
but how i get time without doing it over IrrlichtDevice method? therefore i simply use:
_timeForStand = pOwnerGame->getTime();

and in baseGame class i have method getTime wich is like:

Code: Select all

u32 baseGame::getTime() const
{
  return ( getIrrDevice()->getTimer()->getTime() );
}
where getIrrDevice() is:

Code: Select all

IrrlichtDevice* baseGame::getIrrDevice()
{
  return _irrDevice;
}
it is ok?

i know that there're better solutions but i can't re-design code better on this moment, but i'm still on thinking of it.

maybe someone of you would help me with this as well as with rimbou's situation?

i know that the solution is near with so-called 'interfaces', which would have my base Game class.

well, i'm on thinking...
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

hello again!

hmm, i re-designed much of my code and there's only several troubles i have to solve. One of them is that i have to create my special animator, which i've coded, in methods of my baseObjectState derived classes (which are designed for automatic switching current botMonsters mood,
depending on the situation and 'environment'), and therefore i have to find a way of how to retrieve currentTime to these animators (a time, which is returned, for example, from irrDevice->getTimer()->getTime() ). I know that i would achieve this by means of winAPI functions, but
i don't want to use it, because all my written 'game system' is about using irrlicht engine and its opportunities, and therefore it would be better to find a suitable way of doing this by means of irrlichtDevice rather than by the other 'alternatives'.
Storing in baseOjectState class *_pIrrDevice as a private member doesn't looks good too.
Maybe i would retrieve *_pIrrlichtTimer variable in baseObjectState's constructor and then use it directly? is it ok?

and who knows what will be added later in my baseObjectState derived classes, and what the other irrlicht features they would require? that's a problem i am thinking about..

but in any case i want to avoid of storing a *_pIrrlichtDevice in these classes. maybe i have to design some additional helpful interfaces for my baseGame class and to retrieve the pointers on them to all these 'game's subsystems' such as this baseObjectState' derived classes?
and then all 'dirty' work of doing such irrlicht related things as getting current time as above will rely on them?

then i would write in my baseObjectState derived classes methods smth like:

Code: Select all

u32 time = _pointer_to_my_helpful_interface_which_is_in_my_baseGame_class_nevertheless->getTime();
or, say

Code: Select all

bool collided = _pointer_to_my_helpful_interface->CheckCollision(...);
but i nevertheless think that there're better solutions and a solution above will be wrong, if we'll be discussing this, paying our attention to the OOP and OOD rules/dogmas.

thanks for help!
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

I don't know anything about your project and the current state of it, so I have to stay vague in my answers.

It seems you're doing the detail work before you've cut down your project into chewable parts. I usually (haha, so far only two medium to large hobby game projects) start by breaking down the project into sub-systems. Like graphics, physics, ai, user interaction, game logic, etc... Those are layered, meaning the interaction is, save for callbacks, one-directional.

The game-loop does work on these subsystems using a very high-level interface. Usually with a Facade class.
Getting user input, AI thinking, physics update, graphics update, etc..

Within these subsystem, the same facade class or other helpers have a service interface for smaller specialized classes within the subsystem.

This for the larger picture, now to your problem.
Problematic in your case seems the control-flow. Do those bots really need to get the time, or might it not be better to give them the time. Push instead of pull.

Say, you have an ai subsystem in your project. The game loop calls an advance(float time) function on the ai facade class. Then the facade can determine all active bots, since it manages those and let them do their thinking over a well defined interface. For instance by also calling advance(float time) on those bots.

This way you streamline control-flow and you ensure, that your classes only have access to what they need and thus prevent the interface from getting cluttered and classes calling each other all over your project with you loosing control over what class depends on what other. Trust me here, this happens faster than you think. ;)

Of course time is not the only knowledge your bots need. Determine what is needed and lay out the interface. Decide if you should push it, or if the classes need to pull it. If pulling, from where. Imho only the subsystem facades should have access to irrDevice and grant access over their own interfaces. Not only does it shield your project better from interface changes in irrlicht, since you have now only few places where you need to change your code. But you also minimize dependencies on class level.

The game object class hierarchy for all the entities in your game is difficult to design and thus it is important to give it *really* much thought. I know nothing about your project, as said already, so still vague here.
First of all: Don't even think about making it a SceneNode. ;)
The SceneNode should be either a member of you GO class or be wrapped by a graphics subsystem wrapper class, but not a child class of SceneNode.

My approach is to have a GameObject class with its childs (Creature, < Item < Container, Weapon, Armor). The child classes are only done for fundamentally different concepts that have to be handled differently on a higher level, the rest is data-driven.
A GameObject has some members, a wrapper for the graphical representation, one for physics, one for sound. The game logic only uses this class for interaction, and does not directly control physics or graphics. The GO itself does this, based on the state of it.

HTH
Saturn
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

hello!
Saturn, many thanks for such informative answer.
actually, i have had all these ideas in my mind from the very start of my project. the bad thing is i'm not so good at 'code design' topic, because i'm not so experienced here on this moment.
one thing i didn't understand is your advice to not to make game objects as ISCeneNode. I'm storing scene::ISceneNode* _pNode in my game object's derived classes private fields for getting/setting object's position, etc. is it ok here?
maybe someone would give me a good link on 'code design' articles or useful game sources to get the main idea?
thanks!
Youen
Posts: 4
Joined: Sun Nov 26, 2006 5:30 pm

Post by Youen »

Just to explain why the code of the first post didn't work (since I think nobody explained it) :

your first file includes the second file, its ok
but the second file includes the first file, which gives you infinite recursion (first includes seconds includes first includes second, etc.).

In your case, the use of

Code: Select all

#ifndef _CLASS_1_H_ 
#define _CLASS_1_H_ 
...
#endif
solves the problem of infinite recursion, because the compiler can not enter twice in the same file (the second time, it will skip the file because _CLASS_1_H_ is already defined). Thats why if your first file includes the second, and the second includes the first, the second file will not "see" anything of the first because _CLASS_1_H_ is already defined, and then references to class1 will not be understood by the compiler.

As said above, one solution is to explicitely tell to the compiler that a class named "class1" exists even if it has not seen its declaration yet, but this will only allow to declare pointers to it, not to use any member of the class. You can of course include class1.h in class2.cpp, which will allow you to really use your pointer to class1.
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

varnie wrote:I'm storing scene::ISceneNode* _pNode in my game object's derived classes private fields for getting/setting object's position, etc. is it ok here?
That's fine. You're shielding the scene node this way, and don't give other classes access to it directly. This would often lead to dirty hacks ("nah, I don't need another function in my GameObject, I can just do it directly on the node...") which make code more difficult to maintain.
varnie wrote:maybe someone would give me a good link on 'code design' articles or useful game sources to get the main idea?
thanks!
I use this book, though I don't know many books about game design and can't say how it competes with others. I am quite content with it, though the programming part is small, maybe a quarter.

Jeff Plummer has his Master Thesis on game architecture on his homepage. But the homepage is not active anymore. The thesis lays out one design, which he discusses in relation to others. The trade-off discussion is quite interesting. The read is a bit dry of course.
Nevertheless, here it is. (And no, you don't have to know this name. ;))
varnie
Posts: 31
Joined: Wed Jul 19, 2006 8:27 pm
Location: Russia, Ural

Post by varnie »

hello all!

i still have no working ideas on this.
will someone of you be so please to show me a mechanism of 'requesting' a game class to make that and that for current game's object which is on its 'low' level? i think i need some class for doing all this 'dirty' work, so i could 'ask' it to request that and that, set that and that. is it ok, if i create some big class for doing all this stuff? but then it will have to have many methods for getting that and that, creating that and that, etc etc.
where's a solution?
Saturn
Posts: 418
Joined: Mon Sep 25, 2006 5:58 pm

Post by Saturn »

varnie wrote: where's a solution?
Where is a problem?
I don't understand what you mean, can you provide an example please?
What actual situation do you want to handle how?
Post Reply