View Full Version : What is the difference between these 2 ways of declaring a class object?
While I was reading some C++ code, I saw a code snippet which declared an object like this:
#include <string>
#include <cassert>
#include "BaseGameEntity.h"
#include "Locations.h"
class State;
class Miner : public BaseGameEntity
{
private:
State* m_pCurrentState;
.....
};
Another way of declaring an object is to include the header file and then declare the object in the class:
#include <string>
#include <cassert>
#include "BaseGameEntity.h"
#include "Locations.h"
#include "State.h"
class Miner : public BaseGameEntity
{
private:
State m_pCurrentState;
.....
};
Yes, in the first code snippet, an object pointer is declared while in the second one, it is a normal object.
Other than that,what is the difference between these 2 ways of declaring an object?
When should either method be used? :huh:
Sol_HSA
11-30-2008, 08:30 AM
Yes.
Just saying
class someorother;
is a forward declaration. You can have pointers to such classes, but since the compiler does not know anything about it, you can't call its members or even define it anywhere where the size of said class is needed.
Both ways are useful sometimes. Apart from cutting compile time, that method can be used to hide things.
So to clarify: if you include the whole class definition, you can declare it as a "normal" variable as well as a pointer to said variable. If you only have a forward declaration, you can only have a pointer.
kariem2k
11-30-2008, 09:45 AM
Forward declaration helps most in cases of circular dependency between two classes.
when you include class1 in the header file of class2 which has a pointer to class1 (which is not defined yet because the include statement is before class1 declaration itself) that will cause compiler errors.
so in class2 we just add
class class1;
to tell the compiler that there is actually a class called class1 and you will find it later.
karligula
12-06-2008, 08:36 AM
My personal preference is for a header to always include headers that define classes used in that header. Otherwise you get into situations where you include a header and it doesn't compile because it needs some obscure class and you've got no idea where the damn thing is defined. Which is a big gripe of mine in the engine at work. So long as you have include guards in each header it makes things a lot easier to maintain. The only situation where you really need bare class declarations is in the aforementioned case of forward declarations.
Reedbeta
12-06-2008, 09:11 AM
Doing that can also unnecessarily worsen your compile times since your .cpp files get longer. I prefer to always forward declare classes used in a header whenever possible, switching to including only if I need the full definition.
SmokingRope
12-06-2008, 10:21 AM
I think you can use the PIMPL idiom (http://c2.com/cgi/wiki?PimplIdiom) to cut down compile times, but it will add a little bit of runtime overhead. And in terms of compile times it won't achieve much more than you get with proper dependency management.
It would be nice if there was a free tool to help in optimizing dependencies.
.oisyn
12-06-2008, 08:02 PM
Otherwise you get into situations where you include a header and it doesn't compile because it needs some obscure class and you've got no idea where the damn thing is defined.
Then you're not doing it right. I too think that a header should be functional by itself (as in, you should never get errors just by including it). The header should do this by using forward declares as much as it can, and include any header for which definitions are truely needed.
And if you can't find your definitions, you're not using a proper IDE (or the proper plugins for your IDE). Nor documentation-tools.
As for the TS, in the first example you have a pointer, which (usually) takes up less space in your class (of course not on the heap). The advantages of heaving a pointer to an object are that you can delay-construct it, you can point to objects you don't "own" with it, or it can simply avoid you from having to include it's header in your header as you have already demonstrated. The downside is that you have an extra indirection, which can hurt performancewise for performance critical code (complexer machine code, less cache locality and thus more cachemisses and all that)
karligula
12-07-2008, 06:23 AM
.oisyn, yes exactly you include headers that are truely needed, that's what I was trying to say. I'll have to disagree with Reedbeta though and say you should use forward declarations as little as possible ;-) I guess I just prefer having the full definition to hand at all times.
And how on earth did you guess we're not using a proper IDE? I'm in awe... because that's another of my bugbears at work, we do everything through a command line using hand edited makefiles and scripts and they're mind boggling complicated... I daren't edit them, they're thousands of lines long and the least little change breaks the whole thing. I would dearly love to actually use an IDE but we're utterly locked into these archaic development practices.
Plus, compile times in our codebase are actually barely affected by the number of includes, it's the linking that takes ages. So I would rather include the whole definition of a class so you can create value instances of it rather than trying to be clever and only forward declare it so you can only define pointers to it. In my private projects I never have any trouble with my headers, I can include any file anywhere and it will always compile. Whereas at work, I include something innocent looking and the compiler throws a fit, because people try these tricksy ways of avoiding including something to shave half a millisecond off their compile times.
Everyone has their own style of course... ;-)
.oisyn
12-07-2008, 08:09 AM
.oisyn, yes exactly you include headers that are truely needed, that's what I was trying to say. I'll have to disagree with Reedbeta though and say you should use forward declarations as little as possible ;-) I guess I just prefer having the full definition to hand at all times.
So you're not ageeing with me, as I'm agreeing with Reedbeta. I'm saying: if you can get away with a forward declaration, you should do that :).
The one exception to this rule however might be function return types. You don't need a definition for the return-type in the header, but as soon as you call that function (or method) without actually *using* the return value you'll need anyway it otherwise the compiler doesn't know how to destroy the object. However, you could argue that when using that function you're interested in it's return-type anyway, so you probably already included that particular header in your code.
And how on earth did you guess we're not using a proper IDE? I'm in awe...
Because any proper IDE would allow you to find a specific definition in your code (in VC++: right-click on the symbol and then "goto definition" in the context menu, or even better when you have Visual Assist installed, open the Find Symbol in Workspace dialog which brings up a list of *all* the project symbols, which gets filtered down as soon as you start to type the symbol which you want to find, and it brings you to the point of definition in code when clicking on a symbol), or at least has some "find in files" feature where you can search all project files for a certain phrase :)
Thank you all for the comprehensive replies :worthy: :D
Regarding forward declarations, if the class .h and .cpp files are placed in another directory, does it still work?
Like if we were to use header files, we could just use this:
e.g. #include "..\Level\LevelManager.h"
Regarding forward declarations, if the class .h and .cpp files are placed in another directory, does it still work?
Like if we were to use header files, we could just use this:
e.g. #include "..\Level\LevelManager.h"
Sure. Lots of projects put their public interfaces in header files separate from the rest. You can either use relative paths like in your example, or configure the project to look for header files in certain folders. For instance with Visual C++ the 'C/C++' Property Page of a project has the "Additional Include Directories" string. It could contain for instance ..\Level which means you can just write #include "LevelManager.h".
Rofar
12-10-2008, 08:49 AM
I use includes unless I have to forward declare to avoid circular dependency. Compile times are not impacted that much assuming you take steps to deal with that and use pre-compiled headers.
vBulletin, Copyright ©2000-2010, Jelsoft Enterprises Ltd.