Should I include or make a pointer?

Started by
8 comments, last by cozzie 11 years, 3 months ago
Hi,
I've decided to recheck my whole application (3d engine) code structure, including finding the best of using headers, includes and forward declarations.

So far I used the following guidelines (100% used):
- headers don't include other headers
- if my class in a header has a function definition which needs an object of one of my other classes, I use a forward declaration. Example:

// d3d.h
#ifndef D3D_H
#define D3D_H

namespace MyEngine
{

class D3DScene;

class D3D
{
public:
void RenderScene(D3DScene *myScene)
..
...
}

This works for 90% of my code and structure.
Where I go wrong is in the following situation:

// d3d.h
#ifndef D3D_H
#define D3D_H

namespace MyEngine
{

class D3DFont;

class D3D
{
public:
D3DFont justafont; // this line produces the compiler error
...

void function1(D3DFont *fntpointer);
void function2(D3DFont &fntinstance);
void function3(D3DFont fntobject);
};

// d3dfont.h

class D3DFont
{
public:
// vars etc.
};

When I compile this, I get "D3D::justafont' uses undefined class 'MyEngine::D3DFont'
(not 100% the code, but pseudo good enough).

I studied some articles on forward declarations and understand that I can use them in my class header when:
- I pass through a object pointer in one of my member functions (like above; function1)
- I pass through an instance of an object in one of my member functions (like above; function2)
- It's not possible to pass through a complete object in a member function with forwar declaration (instead #include the header with the class definition) (likeabove; function 3)

In short;
- Can I have D3DFont justafont as member of D3D class, not being a pointer or var in a member function, using a forward declaration? (or do I have to include the header where D3DFont is declared?).
Maybe I already have an idea, because using D3DFont *myfonts; in the D3D class compiles without problems..
Only I don't see the logic in having a member variable (font object) declared as a pointer since it's not (as far as I understand).

Any help or advice is really appreciated.
I'm looking for the best way reduce includes in my D3D header in this case, and using forward declarations when possible.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement
If you are going to start changing members to pointers, you might as well go all the way and use the pimpl idiom.

Either way, there is a maintenance and runtime cost, and you should consider whether it is worthwhile. It's not just a question of good or bad style.

Thanks for the quick reaction. What do you mean with 'pimpl idiom'?

To be honest, I don't see any functional problem or readibility problem using forward declarations for objects what are passed through as pointer or instance in member functions and use includes for class definitions of classes that are an actual member of the other class.

What does make it more readable/ logic for (looking at today's size of the app), is drawing a clear line in usage between members within a class and objects that are passed through within member functions.


For example:

//d3d.h

#include "d3dskybox.h"

namespace myEgine

{

class D3Dcamera;

class D3Dsomething;

Class D3D

{

public:

skybox mySkybox;

bool DoSomethingWithCam(D3Dcamera *pCamera);

void DoSomethingWithSomething(D3Dsomething &pSomeThing)

..

..

};

To be honest when I write this out, it 'feels good' right away, with the pro's:

- good readable/ clear situation for my to read and write

- no unneccesarry includes in headers

- not making pointers of something that's not a pointer, only to be able to do forward declaration instead of include

Do you see any con's?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

As an addition, do you know the difference between:

class D3Dskybox;

namespace myEngine

class D3D

{

void somefunction(D3Dskybox *pBox);

};

and

namespace myEngine

class D3Dskybox;

class D3D

{

void SomeFunction(D3Dskybox *pBox);

...

...

};

The 2nd sounds most logic to me, because D3Dskybox is also a class within the same namespace.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Thanks for the quick reaction. What do you mean with 'pimpl idiom'?

To be honest, I don't see any functional problem or readibility problem using forward declarations for objects what are passed through as pointer or instance in member functions and use includes for class definitions of classes that are an actual member of the other class.

I'll let you google for the details, but basically you hide the entire implementation of a class behind a pointer. It reduces the header to the public interface only, but it does come with a cost.

If you don't want to go that far, forward declaring types used only in the interface as pointers or references is absolutely worth it.

I just did the changes and it's good to read and use.

Thanks again for the help.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

For another opinion on headers, I found a useful post awhile back:
http://www.cplusplus.com/forum/articles/10627/

Specifically in section 4:

There are two basic kinds of dependencies you need to be aware of:
1) stuff that can be forward declared
2) stuff that needs to be #included

If, for example, class A uses class B, then class B is one of class A's dependencies. Whether it can be forward declared or needs to be included depends on how B is used within A:


- do nothing if: A makes no references at all to B
- do nothing if: The only reference to B is in a friend declaration
- forward declare B if: A contains a B pointer or reference: B* myb;
- forward declare B if: one or more functions has a B object/pointer/reference
as a parementer, or as a return type: B MyFunction(B myb);
- #include "b.h" if: B is a parent class of A
- #include "b.h" if: A contains a B object: B myb;

It sounds like this is what you're doing, although you're limiting your code to the top section of the list. The article does have quite a bit more useful information, though.

Thanks, the last one in the list was my initial problem.
I'll do some extra checks against the list, though i think most are covered.

With one difference which for me works more readable/ usable:
- if a has an object of b as member, do include
- if a has a array (pointer) of b's i could forward declare bacause it's it's a pointer, but i now use an include for that too (in line with having b as a single object member)

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

There's just one thing to remember when thinking about whether you need to provide a full declaration of a class/type, or just a forward declaration: Does the compiler need to know the size of the class/type in question in order to compile the code? That's really all there is to it.

Consider the following examples:

// pass-by-pointer. the compiler doesn't need to know what sizeof(MyClass) is, but only that this class exists. a forward declaration suffices.

void Function(MyClass* instance);

// pass-by-value. the compiler needs to set aside stack memory for the temporary, hence it needs to know sizeof(LightWeightType). a full declaration is therefore needed.

void Function(LightWeightType value);

// a member of a class. in order to determine sizeof(A), sizeof(B) needs to be known. hence, a full declaration is needed.

class A

{

B member;

};

Hope that helps!

Thanks, that really works as a guideline.

For all but one situation I can explain my current code and how I do it.

Only thing I don't get is this:

- Class D3Dscene includes member: class D3Dmesh *meshes;

Here I find it a bit doube, on one hand D3Dscene doesn't need to know the size (also not known yet without a 'new' statement), on the other hand it is a member of D3Dscene...

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

This topic is closed to new replies.

Advertisement