Sort of complex inclusion/undefined class problem.

Started by
8 comments, last by Emmanuel Deloget 17 years, 7 months ago
I have a base class, called Module. Two other classes, FontModule and GraphicsModule, publicly inherit from Module. Module keeps, as part of its member data, a pointer to a structure called a Framework. Framework, in turn, keeps pointers to a FontModule and a GraphicsModule structure. Roughly, the situation looks like this: Module.hpp

#include "Framework.hpp"

class Framework;

class Module
{
Framework * framework;
};

FontModule.hpp (looks the same as GraphicsModule.hpp except for name changes

#include "Module.hpp"

class Framework;

class FontModule : public Module
{ //Errors occur on this line!
};

Framework.cpp

#include "FontModule.hpp"
#include "GraphicsModule.hpp"

class FontModule;
class GraphicsModule;

class Framework
{
FontModule * font;
GraphicsModule * graphic;
};

Of course, this is an extremely stripped-down version containing only relevant code. This is the compiler error this generates: error C2504: 'GUI_Module' : base class undefined These occur on the line specified in FontModule and GraphicsModule (the same error in each). How should I change the code so I can compile this? Can I? Thanks very much.
my siteGenius is 1% inspiration and 99% perspiration
Advertisement
What the hell are you trying to do? Currently, either a FontModule or GraphicsModule may contain a Framework, which in turn may contain one of each of those, thus building a tree of Modules. Is that really what you want? Or did you just want that the Framework has a reference to its "parent" module, whichever type it is, and the other pointer will be NULL? In that case, you should just have a Module*, and make proper use of polymorphism. But circular pointer structures are still a warning sign most of the time.

You are strongly advised to read this and this (and possibly other nearby chapters in the C++ FAQ Lite).
I believe he's trying to group up modules in frameworks. Therefore, he would obtain not a tree, but rather a forest of one-level trees with frameworks as roots and a pointer-to-parent in each leaf.

The key here is that the #include"framework.hpp" is not necessary if you only define a pointer to a Framework: a forward declaration will suffice. Only include the entire header file when you actually need details about what a framework actually is.
Quote:Original post by Zahlman
What the hell are you trying to do?


Charming as ever eh Zahlman!
You haven't given quite enough information for me to provide you a concrete illustration of what's going on, however, I strongly suspect that the issue is as follows:

For a given translation unit (whichever one is failing to compile), your "complex" file inclusions are resulting in a preprocessed file that has the definition of the child class BEFORE the definition of the base class; thus the error. If you configure your compiler to generate a dump of the preprocessed file (or do it manually) this should become obvious.

Note that include guards are not *neccessarily* the solution to the problem -- the solution involves reducing include interdependancies, as others have previously mentioned. If you are only using pointers, you need only forward declare the class and not bother with the include. You will need to include the base class definition in the header for the child class, however, as the compiler requires the full definition in order to know sizes, et cetera, when deriving.
Quote:Original post by Anonymous Poster
Quote:Original post by Zahlman
What the hell are you trying to do?


Charming as ever eh Zahlman!


Indeed! <3
You're a wonderful person, Zahlman :) Maybe I'm asking the wrong question, and what I should be figuring out is a non-obscenely-hellish-and-confusing way to structure this. Tell me if you can think of one. This system has been coded all past the hour of 10:00 PM, which is itself a warning sign of poor design! I've been trying to think of a better way to do what I'm trying to do, but the issue is that I want to have these modules that deal with different tasks (this is for a GUI system, but that is neither here nor there, really). Hence, the font module, graphics module, and anything else I will need.

Each module is contained within a Framework structure. Hence, any object that knows about the Framework can use any of the modules it contains. However, some modules need to interact (the font module needs to be able to draw text to the screen, which is the responsibility of the graphics module, for example). Hence, each module has a pointer back to the framework that contains it so that they can make use of the other modules in the framework. Maybe I'm not giving the modules responsibilities in the most sensible fashion, I don't know.

If you can think of any better way of organizing this, let me know. Otherwise, to let you know, removing the include of Framework.hpp from Module.hpp let the code compile, so thanks very much no matter what!
my siteGenius is 1% inspiration and 99% perspiration
0) What is a framework?

1) You don't need classes to make code modules. Classes are to define *types*. If you have a FontModule and a GraphicsModule that are both Modules... well, what is the common interface of a Module? What do you *do* with a Module? Can you instantiate several of them? Can they be serialized in any meaningful way?

A Font, for example, makes sense as a class type. You can have an instance of it, which represents a combination of a typeface, leading, kerning, point size and emphasis flags. You can associate a Font with a fragment of Text. But what is a FontModule? Is it, for example, a thing that accepts Text with a Font and renders it to the screen? Would you benefit from having more than one? Why not make rendering be something that the Font can do? That's a reasonable interface for a Font: You give it some string, and say "draw it here according to how you make text look". Reasonable, for something that represents an appearance-of-text.
Quote:Original post by Zahlman
0) What is a framework?

1) You don't need classes to make code modules. Classes are to define *types*. If you have a FontModule and a GraphicsModule that are both Modules... well, what is the common interface of a Module? What do you *do* with a Module? Can you instantiate several of them? Can they be serialized in any meaningful way?

A Font, for example, makes sense as a class type. You can have an instance of it, which represents a combination of a typeface, leading, kerning, point size and emphasis flags. You can associate a Font with a fragment of Text. But what is a FontModule? Is it, for example, a thing that accepts Text with a Font and renders it to the screen? Would you benefit from having more than one? Why not make rendering be something that the Font can do? That's a reasonable interface for a Font: You give it some string, and say "draw it here according to how you make text look". Reasonable, for something that represents an appearance-of-text.


0 + 1) The framework is the name I gave to the structure that just stores all the different modules. They've all got instances in the framework and due to the pointers to and from the two structures they can all use the different features of the other modules. Thus, the FontModule, which is responsible for loading, storing, and rendering text to an SDL_Surface (which is what this GUI is using for graphics) can use the GraphicsModule to blit the surface to the target render surface (which isn't necessarily the screen, hence necessitating the graphics module which deals with this among other related responsibilities).

Modules aren't just used to wrap function calls - the font module, for example, can load a certain font from a file, and generate new font files at different sizes when needed. The control module stores the controls (push button etc) used by the GUI, and manages their memory and their updates.

Now, I think you have a point in terms of whether this makes sense or not, especially in the case of the fonts. It would make sense for the individual font to be able to render text itself - the way I'm doing it, the control tells the font module that it wants to render this text, here, in this color, with this font. The font module retrieves the font of the appropriate size, and renders the text in the appropriate location. It also performs formatting if necessary, to manage rendering multiple lines of text. Most of this seems like something the font could do. In fact, this seems, upon reflection, to be procedural programming wrapped up in an ugly pseudo-OOP structure. I'm starting to sound like you, Zahlman!



So how does this sound instead: all fonts, graphics used by the GUI (like a close button) and other such flotsam are stored in one structure, which controls have access to. These graphics are responsible for rendering themselves. Controls have access to this encompassing structure and can retrieve the objects they need from it. The flow might look a bit like this:

A text field needs to render its caption, so it accesses its stored instance of what we'll call the "Graphics System".  It tells it to render some text, with certain attributes.  The Graphics System finds the appropriate font, and tells the font to render the requested text to a certain position.  The font takes the text, formats it appropriately, and blits it to the appropriate position.


The original looked like this, and diverges about halfway through from the above:
A text field needs to render its caption, so it accesses its stored framework object, and retrieves the font module.  It then tells the font module to render some text, with certain attributes.  Then, the font module retrieves the requested font object of the appropriate size, uses the data stored there to render the text, and then returns the text texture to the control.  The control then gets access to the graphics module from the framework, and tells it to render the texture in the appropriate spot.


Well, I think I have some reworking to do, but thanks for the intense questioning, Zahlman - it made me rethink the design, and I think that this way makes a lot more sense.
my siteGenius is 1% inspiration and 99% perspiration
Quote:Original post by silverphyre673
0 + 1) The framework is the name I gave to the structure that just stores all the different modules. They've all got instances in the framework and due to the pointers to and from the two structures they can all use the different features of the other modules. Thus, the FontModule, which is responsible for loading, storing, and rendering text to an SDL_Surface (which is what this GUI is using for graphics) can use the GraphicsModule to blit the surface to the target render surface (which isn't necessarily the screen, hence necessitating the graphics module which deals with this among other related responsibilities).

Modules aren't just used to wrap function calls - the font module, for example, can load a certain font from a file, and generate new font files at different sizes when needed. The control module stores the controls (push button etc) used by the GUI, and manages their memory and their updates.

Now, I think you have a point in terms of whether this makes sense or not, especially in the case of the fonts. It would make sense for the individual font to be able to render text itself - the way I'm doing it, the control tells the font module that it wants to render this text, here, in this color, with this font. The font module retrieves the font of the appropriate size, and renders the text in the appropriate location. It also performs formatting if necessary, to manage rendering multiple lines of text. Most of this seems like something the font could do. In fact, this seems, upon reflection, to be procedural programming wrapped up in an ugly pseudo-OOP structure. I'm starting to sound like you, Zahlman!

So how does this sound instead: all fonts, graphics used by the GUI (like a close button) and other such flotsam are stored in one structure, which controls have access to. These graphics are responsible for rendering themselves. Controls have access to this encompassing structure and can retrieve the objects they need from it. The flow might look a bit like this:

1 : A text field needs to render its caption, so it accesses its stored instance of what we'll call the "Graphics System". It tells it to render some text, with certain attributes. The Graphics System finds the appropriate font, and tells the font to render the requested text to a certain position. The font takes the text, formats it appropriately, and blits it to the appropriate position.

The original looked like this, and diverges about halfway through from the above:
2 : A text field needs to render its caption, so it accesses its stored framework object, and retrieves the font module. It then tells the font module to render some text, with certain attributes. Then, the font module retrieves the requested font object of the appropriate size, uses the data stored there to render the text, and then returns the text texture to the control. The control then gets access to the graphics module from the framework, and tells it to render the texture in the appropriate spot.

Well, I think I have some reworking to do, but thanks for the intense questioning, Zahlman - it made me rethink the design, and I think that this way makes a lot more sense.


While 1 makes sense from a design point of view, I find 2 somewhat over-engineered (though it is not that horrible).

Anyway, it doesn't explain why Module should know about the framework - unless there is a nasty dependency I don't see yet. Your circular dependency is dangerous. In the end, it means that the module class is able to know its child classes (which doesn not make much sense from a OO point of view) or that the framework is able to know itself in a redundant way. Pointer-to-parent is always a bad idea in situations like this.

There is another issue; what does the Module class do? Is there really an inheritance link between Module and FontModule? If yes then you are in trouble, because FontModule does not act like a module - it acts like a font module, and has no meaning at all if you use it through the Module interface. If Module is only used to share some code between the different modules, you should prefer composition over inheritance (add a Module member to your module classes). You'll have the same functionality and you'll get rid of some hard-to-spot problems that may arise if you don't use inheritance and function overloading in the correct way.

HTH,

This topic is closed to new replies.

Advertisement