Jump to content

  • Log In with Google      Sign In   
  • Create Account

Should I include or make a pointer?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 11 January 2013 - 03:33 PM

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.

Edited by cozzie, 11 January 2013 - 03:35 PM.


Sponsor:

#2 EWClay   Members   -  Reputation: 659

Like
2Likes
Like

Posted 11 January 2013 - 03:53 PM

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.

#3 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 11 January 2013 - 04:32 PM

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?



#4 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 11 January 2013 - 04:38 PM

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.



#5 EWClay   Members   -  Reputation: 659

Like
0Likes
Like

Posted 11 January 2013 - 05:04 PM

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.



#6 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 11 January 2013 - 05:06 PM

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

Thanks again for the help.



#7 tsolron   Members   -  Reputation: 107

Like
0Likes
Like

Posted 12 January 2013 - 02:42 AM

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.



#8 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 12 January 2013 - 06:12 AM

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)

#9 tivolo   Members   -  Reputation: 990

Like
0Likes
Like

Posted 15 January 2013 - 08:29 AM

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!



#10 cozzie   Members   -  Reputation: 1764

Like
0Likes
Like

Posted 15 January 2013 - 11:52 AM

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...






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS