Skip to main content
gamedev.net
🔒 Locked

OGRE's forward declaration

Started by okonomiyaki Sep 4, 2006 at 10:43 AM 8 replies 1.7k views
Original Post
okonomiyaki
okonomiyaki
OGRE forward declares all its classes in the standard include:

// Pre-declare classes
// Allows use of pointers in header files without including individual .h
// so decreases dependencies between files
    class Angle;
    class Animation;
    class AnimationState;
    class AnimationStateSet;
    class AnimationTrack;
    class Archive;
    class ArchiveFactory;
    class ArchiveManager;
    class AutoParamDataSource;
    class AxisAlignedBox;
    class AxisAlignedBoxSceneQuery;
    class Billboard;
    class BillboardChain;
    class BillboardSet;
    ...

Sure, it decreases dependencies, but you don't have to do it this way. You can forward declare a class in another class's header file. This makes OGRE hard to study as it's not clear what classes depend on what. You should be able to look at a .h file of a class and see exactly what it depends on by looking at what classes are included or forward declared. But I may be wrong on my opinion. What do you think about this technique? Also, I'm curious to know other people's rule on whether you include a file or just forward declare the class. I typically include the class if I can because I like to just be able to include one file and know that I can use the class rightly. Dependency issues will force otherwise of course though.
cruppstahl
cruppstahl
i forward classes and structures as often as possible. Including files slows down the build process. Sure, it's not much, but if you have a big project with a lot of include files which include each other, you will notice it.

Also, you often have the chicken-egg-problem, when two header files include each other; in such a case you need the forward declaration anyway.
Aardvajk
Aardvajk
I only forward declare classes when I absolutley have to because:

a) there is an interdependance so the full class info can't be available at the point I need it.

b) I am hiding the implementation of the class to reduce interdependance.

Given the speed of modern computers, I think the affect of file inclusion on build times is negligible. Class forward declarations have a specific purpose and are not meant to be used to speed up compilation IMHO.
okonomiyaki
okonomiyaki
Quote:
Original post by cruppstahl
i forward classes and structures as often as possible. Including files slows down the build process. Sure, it's not much, but if you have a big project with a lot of include files which include each other, you will notice it.

Also, you often have the chicken-egg-problem, when two header files include each other; in such a case you need the forward declaration anyway.


You're gonna have to include it at some point though. There may be a few circumstances where something doesn't use that part of the class so you don't have to include a dependant file, but you can't say whenever you forward declare you don't have to include it. It just delays the inclusion.

And yeah, of course there are times when it is necessary. But I just don't like putting all of them into the standard file, but still in the .h to make it clear it's dependant on it.

Edit: EasilyConfused - I agree.
Xai
Xai
But as the OP stated, it doesn't show a coder what the dependencies are, when all classes forward declard all objects. That's the OPs complaint.

The reason they did it though, is cause they don't want to bother tracking dependencies this way. The design and document the API and its logical consequences, whatever way the code dependencies work out is inconsequential and likely to change more than the APIs designed function.

So in other words, if someone sees a usefull optimization caching a pointer to X in class Y - that it obtained by calling a function of class Z. The dependency is mainly between class X and Z ... and the X to Y dependency is transient and implementation details.
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by okonomiyaki
OGRE forward declares all its classes in the standard include:

*** Source Snippet Removed ***

Sure, it decreases dependencies, but you don't have to do it this way. You can forward declare a class in another class's header file.

This makes OGRE hard to study as it's not clear what classes depend on what. You should be able to look at a .h file of a class and see exactly what it depends on by looking at what classes are included or forward declared.

But I may be wrong on my opinion. What do you think about this technique?

Also, I'm curious to know other people's rule on whether you include a file or just forward declare the class. I typically include the class if I can because I like to just be able to include one file and know that I can use the class rightly. Dependency issues will force otherwise of course though.


From a design POV, Ogre has really some insane problems - this is one of them. It makes no sense to forward declare all the exported classes. I suspect they did that because their dependency graph is weird (with a few "ADP ? what the hell is ADP1?").

The standard rule is something along the line of
* forward declare anything you need to create a complete type (to be short: a type whose size can be computed)
* if forward declaration don't work, #include.

This is the rule I am currently using.



1: Acyclic dependency principle
JohnBolton
JohnBolton
I don't know much about Ogre, but does it mean the ogre.h must be included in every file that references Ogre, and must ogre.h always be included first? That isn't very convenient, and in fact it could cause problems.

People frequently sacrifice proper implementation and design principles for the sake of convenience (perceived or actual). It isn't always a bad thing, but you need to be extra diligent in libraries used by lots of people, because what may be convenient for you may be a problem for everyone else.

Quote:
Original post by EasilyConfused
Given the speed of modern computers, I think the affect of file inclusion on build times is negligible.

That's true only for small projects.
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Emmanuel Deloget
Emmanuel Deloget
Quote:
Original post by JohnBolton
I don't know much about Ogre, but does it mean the ogre.h must be included in every file that references Ogre, and must ogre.h always be included first? That isn't very convenient, and in fact it could cause problems.

To Ogre's defense, having a single include file that includes all the other files of the library is a very common practice - most third party libs are built like this, and it's quite convenient to use (with precompiled headers for example). Don't forget that if you design a library, you have to make it simple to use :)

Quote:
Original post by JohnBolton
People frequently sacrifice proper implementation and design principles for the sake of convenience (perceived or actual). It isn't always a bad thing, but you need to be extra diligent in libraries used by lots of people, because what may be convenient for you may be a problem for everyone else.

Still very true.

Quote:
Original post by JohnBolton
Quote:
Original post by EasilyConfused
Given the speed of modern computers, I think the affect of file inclusion on build times is negligible.

That's true only for small projects.

Most companies doesn't use up-to-date computers to build large projects. I, for instance, had to use a dated P3 800 to build a several million line C++ projects some years ago, while some of my coworkers were using a brand new P4 3ghz. Investments are often postponed to save money (in this case, I'm not sure we were really saving money... The project rebuild took 1h30 to 2h00 to complete, and I was barelly unable to use the machine while compiling the project).

Regards,
penwan
penwan
I personally like to have headers be self-sufficient when possible. Thus, if you want to use SomeUsefulClass you #include "SomeUsefulClass.h" and don't have to worry about also including "SomeObscureClass.h" or "SomeOtherImplementationDetail.h" If a class just maintains "opaque" pointers to other classes that are implementation details, then those classes are forward declared.

As to the OP's question, I agree with you WRT Ogre's forward-declare-everything include file.
zedzeek
zedzeek
Quote:
To Ogre's defense, having a single include file that includes all the other files of the library is a very common practice - most third party libs are built like this, and it's quite convenient to use (with precompiled headers for example). Don't forget that if you design a library, you have to make it simple to use :)

i agree completely, simplisticy is the most important thing,
+ whilst the average project size is increasing, computer speeds are increasing at a faster rate. precompiled headers + debug builds == a nice combo for fast compile

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.