Those includes make me mad!

Started by
17 comments, last by tcs 23 years, 11 months ago
Why do you need the full class declarations for other classes in your class declarations? Are you inlining all your functions? Function declarations should never need to know anything more than the names of other classes, neither should variable declarations. About the only reason that you could need the full class declaration for an external class during class declaration is if you are inlining or the class has typedefs or class declarations internal to it. If you are inlining all your member functions, then it''s not really the language''s fault; you''ve suborned the interface/implementation separation inherent to the header/source file distinction.
Advertisement
Think I understand your dilemia here, but correct me if I am wrong.

It is not the classes that you need, it is the structures that are setup in various class definition files (i.e. header files ??)

If that is the case, why not just make a header file with all such structures in it?

If I am wrong and you are trying to reference classes (A) from another class definition (B) which is then referenced in (A) you must forward define the class.

If you don''t like the language, write a new one, that is the way of things.





quote:Original post by tcs

Hey doesn''t anyone have an idea about this ? Is C++ really not able to handel just a few simple include statements ?
Does no one have classes that rely on each other ?


Got tons of cross-linked classes myself. I either forward define them, if they are used as an object inside the class, or I inherit them directly, if I am doing a polymorph of the object.

Looks like my last post was off the mark, so I point you again to the forward class definition. That is the solution.







Correct me if I am wrong, but wouldn''t the easiest solution be to create a series of (I hate to use a microsoft term) of components that build upon eachother.

Example:
Base Vertex Class, holds only a cooridinate, possibly texture coordinate aswell

A Triangle class uses the vertex class to describe the location of its three points.

An object class, uses triangles to describe the object in space.

A world class that contains the objects.

So on and so on...

The way I see it, it is a matter of smart design, I ran into the same dilema awhile back designing a basic telnet chatter to test my skills at berkely sockets, but the same principle applies. If you have two classes that are interdependant of eachother you just defeated the base principle of OOP. Objects should be self contained.

Here are some tips to getting it so you don''t need to classes that use eachother.

1. If data between two classes must be shared, create a separate structure or class for that shared data and pass it from one class to another through a method. But, make sure that one class doesn''t need to know about the other to pass the data, pass the data outside the two classes by calling one of the classes methods.

Example:

class Data
{
public:
int dummyforexample;
};

class MyClass1
{
public:
Data GetData() {return MyData;}
private:
Data MyData;
};

class MyClass2
{
public:
Data GetData();
SetData(Data _MyData) {MyData = _MyData;}
private:
Data MyData;
};

void main()
{
MyClass1 c1;
MyClass2 c2;

... //initialization and other things were left out for simplicity

c2.SetData( c1.GetData() );

}

2. If you have a heirarchy of classes that use eachother (not talking about inheritance), make sure those lower in the heirarchy don''t know about, in other words don''t use, those above them in the heirarchy.

This is what I do, and I rarely run into such conflicts, I learned my lesson awhile back, might as well share what I learned.

-Omalacon
I think I understand your problem and Sicrane and Qoy are right.

An example(I have not tried compiling this so it might be totally wrong!):

aaa.h
-----

#ifndef AAA_H
#define AAA_H

#include "bbb_H"

class aaa
{

bbb *b;

public:

void set_bbb(bbb *new_b);

};

#endif

bbb.h
------
#ifndef BBB_H
#define BBB_H

/*Do not include aaa.h here!*/
class aaa;

class bbb
{

aaa *a;

public:

void set_aaa(aaa *new_a);

};
#endif

bbb.cpp
-------
#include "bbb.h"
#include "aaa.h" /*Here we include aaa.h to get access to its members.*/

void bbb::set_aaa(aaa *new_a)
{

a = new_a;
a->set_b(this);

}

Hope I got that right and that it helps
class XXX;

class YYY {
...
XXX *X;
...
};

Yes... but what should I do when I also need class YYY objects in my class XXX ???

SiCrane: No, I don''t have a single inline function.

Joviex: I already did that, the shared structures are in my big header file.

This is my header file:



// This file contains all includes that are important to the
// Loader / HSR / Renderer stuf

#if !defined(ENGINE_H__INCLUDED_)
#define ENGINE_H__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// Conversion factor for converting between degrees and radians
#define PI_OVER_180 0.0174532925f

// Common libs
....

// Common structures

....

// Common includes

#include "Camera.h" // Camera object
#include "Mesh.h" // Mesh object used by the renderer and filled by the OBJ Loader
#include "OBJModel.h" // OBJ Loader for filling Mesh classes
#include "glext.h" // Extensions for the renderer
#include "Triangle.h" // Lightmap / collision detection triangle class
#include "Renderer.h" // Renders mesh objects

#endif // !defined(ENGINE_H__INCLUDED_)


I include this file in every of my other header files. But OUTSIDE the inclusion
guards. Otherwise it wouldn''t work !? If I change the order of the includes in
this engine.h, I got 100 error messages that some identifiers aren''t declared...

At the moment, everything works. But I''m afraid that everything is broken again, if
I just add one class or use a class in another classed that was unused before. It just
can''t be that you have to figure out each time in which order your classes have to be included...

Omalacon:

And what is if two classes need my triangle class ? My COBJModel class creates a CMesh object and
my Triangle class needs a CMesh object (it has to know about meshes cause it needs to generate lightmaps)
and a COBJModel etc...

maybe you''re right and my OOP approach is wrong, I try if I see a possibility to do it your way...
Tim--------------------------glvelocity.gamedev.netwww.gamedev.net/hosted/glvelocity
It works. I redesigned everything a bit...
Tim--------------------------glvelocity.gamedev.netwww.gamedev.net/hosted/glvelocity
Just picking up on this thread - seems to be about circular dependencies. I''m glad you solved your problem by redesigning a bit TCS, circular dependencies tend to be an indication of a flaw in design. ( There are circumstances when it''s unavoidable though ).

If you do run into a circular dependency, best think is to check why it happens, and then figure out a way to do it so that you do NOT need to know anything about the other class.


#pragma DWIM // Do What I Mean!
~ Mad Keith ~
**I use Software Mode**
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
quote:Original post by tcs

class XXX;

class YYY {
...
XXX *X;
...
};

Yes... but what should I do when I also need class YYY objects in my class XXX ???

SiCrane: No, I don''t have a single inline function.

If you don''t inline the functions, then you really don''t need to know the contents of the classes at declaration time do you? In XXX.h have:
class YYY;class XXX {  public:    YYY * yyy;}; 

and in YYY.h have:
class XXX;class YYY {  public:    XXX * xxx;}; 


Now the problem with your header file was that it includes all these headers, which also include this global header, right?

So you''ve got "Triangle.h" which includes your global header. So with the inclusion guards, the preprocessor will expand things like:
Beginning of Triangle.h// #include "engine.h"Lots of "engine.h" stuff// #include "triangle.h"// skips triangle.h because of the triangle.h inclusion guard// #include "mesh.h"Mesh.h stuff.// #include "engine.h"// skips engine.h because of engine.h inclusion guard.class Mesh {  Triangle * triangle;};// end of Mesh.h// end of Engine.hclass Triangle {  Mesh * mesh;}; 

Your mesh declaration will barf because you don''t have a forward declaration for Triangle. All you need to do is place a forward declaration for Triangle before the class Mesh declaration and all will be good.
You could even put all your forward declarations in the engine.h header, before your includes so it''d look something like:
....// Common forward declarationsclass Triangle;class Mesh;....// Common includes#include "Camera.h" // Camera object#include "Mesh.h" // Mesh object used by the renderer and filled by the OBJ Loader#include "OBJModel.h" // OBJ Loader for filling Mesh classes#include "glext.h" // Extensions for the renderer#include "Triangle.h" // Lightmap / collision detection triangle class#include "Renderer.h" // Renders mesh objects 

And that should solve your problem.

This topic is closed to new replies.

Advertisement