• Advertisement

Archived

This topic is now archived and is closed to further replies.

Circular Depandancies

This topic is 5156 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I could not get rid of them on my exam and I cant get rid of them now. I am having endless problems with circular dependancies with .h files including other .h files that have already been included if you catch me? The result being things such as global variables being declared twice. A friend of mine said you have to use some #ifdef or something? Can someone explain this to me and how to use it (assuming my friend was right)? Thanks as always.

Share this post


Link to post
Share on other sites
Advertisement
Run a search for "inclusion gaurds".

But, how it works is like this:

#ifndef MY_BoxClass_H
#define MY_BoxClass_H

... Put includes here ...

... Put classes here ...


#endif

Basically, this keeps the compiler from reading and defining the same code multiple times.

Also, do not define global variables in a header like such:

int g_Handle;

instead do this:

handle.h

extern int g_Handle;

handle.cpp

int g_Handle;

That way it is not defined multiple times, but other source file know of it''s existance...

Share this post


Link to post
Share on other sites
Thanks, but just one thing...what goes where the MY_BoxClass_H is? I dont understand what this is...

Share this post


Link to post
Share on other sites
That''s a FAQ.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
— Brian W. Kernighan (C programming language co-inventor)

Share this post


Link to post
Share on other sites
Yeah I just found that, thanks anyway

I cant believe we were not taught inclusion guards this semester in software development principals...would have saved me alot of trouble.

Anyhow, thanks again.

Share this post


Link to post
Share on other sites
Watch out for class circular dependency as well (for example, when two classes have members that are of the other class).

Inclusion guards don't entirely prevent them. You need an empty declaration of a class in order for it to work.

class A;
class B
{
A data;
};

class A
{
int value;
B member;
};

I think that works.

[edited by - Waverider on January 12, 2004 12:53:11 PM]

Share this post


Link to post
Share on other sites
You can also use '#pragma once' if you only want a file included once during compilation (if your compiler supports it).

[edited by - arm on January 12, 2004 2:36:56 PM]

Share this post


Link to post
Share on other sites
Hmm for some reason I still cant get rid of some of them. This is what I have in my OpenGL.h file (included in 2 .c files). hDC, hRC, hWnd and hInstance are still causing problems. Actually ifndef didnt seem to solve anything, declaring keys, active and fullscreen, then defining them in the .c file solved the problem with them, but the others are no good. The functions i never had a problem with.

#ifndef INC_OPENGL_H
#define INC_OPENGL_H

#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
//#include <gl\glaux.h>

extern bool keys[256];
extern bool active;
extern bool fullscreen;

extern HDC hDC;
extern HGLRC hRC;
extern HWND hWnd;
extern HINSTANCE hInstance;

GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
int InitGL(GLvoid);
int DrawGLScene(GLvoid);
GLvoid KillGLWindow(GLvoid);
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#endif /*INC_OPENGL_H*/

The problem with the global variables was that i was defining them in the header...not just declaring (i am a bit rusty). However, the other 4 globals are not working, still causing the double defining.

I was also taught that extern actually does nothing as all functions and global variables are globals in C anyway, unless declared static, making them local to the source file...

Share this post


Link to post
Share on other sites
If you post the exact error messages, it will be easier to help solve your specific error.

Share this post


Link to post
Share on other sites
quote:
Original post by Waverider
Watch out for class circular dependency as well (for example, when two classes have members that are of the other class).

Inclusion guards don''t entirely prevent them. You need an empty declaration of a class in order for it to work.

class A;
class B
{
A data;
};

class A
{
int value;
B member;
};

I think that works.

[edited by - Waverider on January 12, 2004 12:53:11 PM]


That doesn''t work. This works.

class Bar;

class Foo
{
Bar * pBar;
};

class Bar
{
Foo * pFoo;
};

You have to use pointers (at least one has to be a pointer) or it won''t compile. It''s not even logical if you really think about it.



-----------
VenDrake

"My stupid jar is full. I can''t talk to you anymore."

Share this post


Link to post
Share on other sites
Inclusion Guards are just the beginning...not the end. There are lots of other problems. Here is another rule of thumb.

Don''t put #include statements in your header unless absolutely necessary. Put them in your .cpp files when possible. Predeclare a class instead of #including it in a header if you can.

To really solve the problem you have to understand the problem. The preprocessor replaces every #include with the contents of the file that you list. Consider FileA.h that includes FileB.h and visa-versa. Understanding this problem is the beginning of understanding the extent of the problem.

The following is a slightly complex solution that comes from lots of experience:
For each group of related files create two additional header files for the group. I will use the example of all Graphics files. Name them InternalGraphics.h and ExternalGraphics.h. Inside your group ONLY include your pch file and InternalGraphics.h (stdafx.h is a pch, if you don''t understand, don''t use one). Outside your group don''t include the class header files, ONLY include ExternalGraphics.h. Organize these two files so that they predeclare classes and then include the files in the correct order.

This solution is obviously overkill for small projects. But it''s a lifesaver for large ones.


// Example InternalGraphics.h
// This file contains ALL files necessary for ANY
// .cpp file in the Graphics Module

#include <list>
#include <map>
#include <math.h>
#include <float.h>
#include <DirectX.h>

// Header for another module
// Graphics Module needs to use parts of this module
#include "ExternalResourceLoader.h"

class VertexData;
class PixelShader;
class GraphicsEngine;

#include "PixelShader.h"
#include "VertexData.h"
#include "GraphicsInterface.h"
#include "GraphicsEngine.h"

// End InternalGraphics.h



// Example ExternalGraphics.h
// This file ONLY contains includes necessary for other
// modules to use the graphics engine

#include <list>

#include "GraphicsInterface.h"

// End ExternalGraphics.h





-----------
VenDrake

"My stupid jar is full. I can''t talk to you anymore."

Share this post


Link to post
Share on other sites
quote:
Original post by Mr Lane
I was also taught that extern actually does nothing as all functions and global variables are globals in C anyway, unless declared static, making them local to the source file...


Whoever taught you that has NO idea what extern does. Extern informs the compiler that the variable is defined in another module, and therefore can''t be resolved until link time.

For more information, google for "separate compilation" or "extern keyword".

Share this post


Link to post
Share on other sites
quote:
Original post by Anthony Serrano
quote:
Original post by Mr Lane
I was also taught that extern actually does nothing as all functions and global variables are globals in C anyway, unless declared static, making them local to the source file...


Whoever taught you that has NO idea what extern does. Extern informs the compiler that the variable is defined in another module, and therefore can''t be resolved until link time.

For more information, google for "separate compilation" or "extern keyword".


Yes but functions and globals are extern by default in C...the extern keyword is merely convention. I doubt Dr. Zoltan Symogi the programming freak at my university is wrong...but then again it might be one to check.

Share this post


Link to post
Share on other sites
quote:
Original post by pjcast
If you post the exact error messages, it will be easier to help solve your specific error.


The error i have been getting is:

OpenGL.c D:\LANEEN~1\lesson01\OpenGL.o(.bss+0x0)
multiple definition of `hDC''

And this happens for hDC, hRC, hWnd and hInstance, but not any of the other variables. The only way i have found to solve it is to take it out of the header, put it in the OpenGL.c file and declare them static...but of couse this means that i cant use them anywhere else. I suppose I can deal with that, but its annoying. What is the problem here?

Share this post


Link to post
Share on other sites
What compiler/linker or IDE is that error message from? Dev-cpp? Just curious...

Well, I can't really tell why it says it's defined more then once. If you only defined it once in your .c file. Perhaps it was defined again in one of the modules that gets linked in.

One suggestion, when you make a global variable, you run the risk of it being declared in other places. And with the generic nature of the variable names (hInstance, hWnd, etc...) there is a big risk that someone else may have used those same names somewhere else.

I would say use namespaces, but it's apparent your using c. SO, you should try changing thier names to something more specific to your app. For example, change hInstance to g_MyGLWinInstance...

Also, you have included both gl.h and glu.h, now I'm not positive whats in both those headers... But do you really need both in the header? I see your using some GL datatypes in the header, but are they defined in both the headers? Or can you remove at least one header to the source file? Just a question.

Edited - Spelling

[edited by - pjcast on January 13, 2004 2:32:54 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Mr Lane
Yes but functions and globals are extern by default in C...the extern keyword is merely convention. I doubt Dr. Zoltan Symogi the programming freak at my university is wrong...but then again it might be one to check.


Just did check. Only function prototypes are extern by default; external variables MUST be explicitly externed.

Share this post


Link to post
Share on other sites

  • Advertisement