Jump to content

  • Log In with Google      Sign In   
  • Create Account


how is stuff done correctly in the C++ World (headers, #include,namespaces)?


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
8 replies to this topic

#1 Bluefirehawk   Crossbones+   -  Reputation: 1232

Like
0Likes
Like

Posted 07 August 2012 - 03:30 AM

I am coming from the Java/C# world. Now I am a bit confused how you do stuff in C++.


Nested Namespaces?
I am used deep nested namespaces and to also have my folder structure according to the them (For example "Core/System", "Core/Graphics/Textures"...). Now I read that in C++, nesting namespaces is not encouraged and is only used to prevent nameclashes.
Is that how you do it in C++? Does a deep folder structure make sense for a C++ project, or is a shallow structure considered standard?


How to include correctly? Observer pattern example
to illustrate my problem, let's say I have an Observer/Observable pattern implemented:
/Core/Observable.h
/Core/Observable.cpp
/Core/Message.h
/Core/Message.cpp
/Observer.h
/Observer.cpp

Now for the Observable can:
#include "Message.h" of
declares "class Message;"

The Observer can:
#include "Observable.h", and implicitly know about the Message class as well, if Observable uses Method 1
#include "Observable.h", #include "Message.h", thanks to header guards this works.
#include "Observable.h" and declare "class Message;"

What's the "right" way to do it, or is there none?


nested headers
I don't know if it is a religious topic, but some sources say nested headers are baaaad. are they?

I saw something like:
global.h
(header guard)
#include <std>
#include "utilities.h"
#include ...

every file included globals.h, is this a common practice or is it stupid?
Project: Project
Setting fire to these damn cows one entry at a time!

Sponsor:

#2 Álvaro   Crossbones+   -  Reputation: 12504

Like
5Likes
Like

Posted 07 August 2012 - 06:48 AM

Nested Namespaces?
I am used deep nested namespaces and to also have my folder structure according to the them (For example "Core/System", "Core/Graphics/Textures"...). Now I read that in C++, nesting namespaces is not encouraged and is only used to prevent nameclashes.
Is that how you do it in C++? Does a deep folder structure make sense for a C++ project, or is a shallow structure considered standard?


It's a matter of style. I generally prefer having only one level of namespaces, which has been enough in all the projects I have worked on (some involving hundreds of thousands of lines of code).

How to include correctly? Observer pattern example
to illustrate my problem, let's say I have an Observer/Observable pattern implemented:
/Core/Observable.h
/Core/Observable.cpp
/Core/Message.h
/Core/Message.cpp
/Observer.h
/Observer.cpp

Now for the Observable can:
#include "Message.h" of
declares "class Message;"

The Observer can:
#include "Observable.h", and implicitly know about the Message class as well, if Observable uses Method 1
#include "Observable.h", #include "Message.h", thanks to header guards this works.
#include "Observable.h" and declare "class Message;"

What's the "right" way to do it, or is there none?


You should generally prefer a forward declaration if that's enough (i.e., if you are only going to declare pointers or references to the class), especially in header files. That way compiling a module won't require reading an extra header file, and a change in the header file will trigger recompilation of fewer modules.

nested headers
I don't know if it is a religious topic, but some sources say nested headers are baaaad. are they?

I saw something like:
global.h
(header guard)
#include <std>
#include "utilities.h"
#include ...

every file included globals.h, is this a common practice or is it stupid?


That's a bad idea. It makes everything depend on everything else. If you made a change in a header file the whole code would need to be recompiled, whether it has anything to do with the change or not. It

You should only include the header files you use. That way you can also identify groups of modules that form sefl-contained units and perhaps promote them to a libraries, which is a useful way to organize code and encourage code reuse.

Edited by alvaro, 07 August 2012 - 06:48 AM.


#3 BitMaster   Crossbones+   -  Reputation: 3792

Like
0Likes
Like

Posted 07 August 2012 - 06:56 AM


Nested Namespaces?
I am used deep nested namespaces and to also have my folder structure according to the them (For example "Core/System", "Core/Graphics/Textures"...). Now I read that in C++, nesting namespaces is not encouraged and is only used to prevent nameclashes.
Is that how you do it in C++? Does a deep folder structure make sense for a C++ project, or is a shallow structure considered standard?


There is one notable exception though, it can be useful to have a subnamespace detail or impl. That becomes mostly useful in large multi-people projects but a subnamespace like that is a warning to every right-thinking person that anything in there should not be touched (unless you really, really know what you are doing and you can live with the fact that the next version of that library might not work with your code, at all).

#4 Bluefirehawk   Crossbones+   -  Reputation: 1232

Like
0Likes
Like

Posted 07 August 2012 - 08:49 AM

You should generally prefer a forward declaration if that's enough (i.e., if you are only going to declare pointers or references to the class), especially in header files. That way compiling a module won't require reading an extra header file, and a change in the header file will trigger recompilation of fewer modules.


Okeeey... so for example the Observable.h would look like this:
class Observable
{
class Message;
private:
	...
	void NotifyObservers(Message me);
	...
}
this would be the best way to do it (considering includes and not the public function).
but then under the same rules it would make sense to just forward declare on the Observer.h as well, and now I have never included the Message.h and the program will probably not link correctly.

In other words, when do I ever use an object in the header file and do more with it than just declaringreference/pointers? Thats what the cpp files are for, i thought.
Thanks for the reply, but it's still not very clear to me.

Edited by Bluefirehawk, 07 August 2012 - 08:51 AM.

Project: Project
Setting fire to these damn cows one entry at a time!

#5 Álvaro   Crossbones+   -  Reputation: 12504

Like
0Likes
Like

Posted 07 August 2012 - 09:41 AM

I wouldn't put a forward declaration inside a class block: C++ has nested classes, so you probably just forward-declared Observable::Message. Also, you can't use a forward declaration in your case, because you are passing a Message by value. If you pass a reference or a pointer instead, it should be fine.

You probably have some part of the program that needs to use the Message class, and at that point you'll need to include Message.h.

If forward declarations are confusing you right now, start by not using them, which is not terrible in most circumstances. When you are more familiar with how header files are used in C++, you can start using them.

Oh, while we are talking about header files in C++: Make sure the first thing you do in foo.cpp is include foo.h. That way you verify that you didn't miss any dependencies in foo.h and it can be compiled by itself.

Edited by alvaro, 07 August 2012 - 09:41 AM.


#6 eFoDay   Members   -  Reputation: 300

Like
1Likes
Like

Posted 07 August 2012 - 10:48 AM

edited post because I mainly use pointers and then I realized it doesnt work on non-pointers.

this is the error you will get:

In file included from main.cpp:10:0:
Observer.h:16:10: error: field 'myMessage' has incomplete type

[source lang="cpp"]class Message;class Observer { Message myMessage; void accessMessage();}[/source]

so actually this gives no error:

[source lang="cpp"]class Message;class Observer { Message* myMessage; void accessMessage();}[/source]

this actually doesn't give an error message either:

[source lang="cpp"]class Message;class Observer { Message* myMessage; void accessMessage() { myMessage->someFunc(); }}[/source]

But trying to access Observer::accessMessage without including the Message header will give an error:

In file included from main.cpp:10:0:
Observer.h:17:49: error: invalid use of incomplete type 'class Message'
Observer.h:11:7: error: forward declaration of 'class Message'

[source lang="cpp"]#include "Observer.h"int main(int argc, char** argv) { Observer myObserver; myObserver.accessMessage(); // error return 0;}[/source]

To fix the error you will need to include the actual header of Message so it knows about the actual functions.

This is the way I usually set up my files:

[source lang="cpp"]// .h fileclass Message;class Observer { Message* myMessage; void accessMessage();}// .cpp file#include "observer.h"#include "message.h"void Observer::accessMessage() { myMessage->someFunc();}[/source]

And without pointers:

[source lang="cpp"]// .h fileclass Observer { Message myMessage; void accessMessage();}// .cpp file#include "message.h"#include "observer.h"void Observer::accessMessage() { myMessage.someFunc();}[/source]

Edited by eFoDay, 07 August 2012 - 11:40 AM.


#7 Bluefirehawk   Crossbones+   -  Reputation: 1232

Like
0Likes
Like

Posted 08 August 2012 - 12:10 AM

Alrigth, forward declaration starts to make sense.
Then I have one last hassle, why do you put your includes in the .cpp files? The Headers can compile without any other classes now, but the body cannot. Is there an upside/downside?
Project: Project
Setting fire to these damn cows one entry at a time!

#8 doeme   Members   -  Reputation: 692

Like
2Likes
Like

Posted 08 August 2012 - 02:23 AM

Then I have one last hassle, why do you put your includes in the .cpp files? The Headers can compile without any other classes now, but the body cannot. Is there an upside/downside?


One of the main reason to do this is to reduce compile-time dependencies between modules and classes by separating the implementation from the declaration in the headers. This will increase the compile-speed and also allow you to separate modules better. Usually you only need to know the declaration (method-footprints) of a class and not the definition (implementation) of said methods in another class. The problem behind it is, that in c++ includes are always visible from the outside even if all the methods and class-attributes are declared private.

One of the downside of forward declaration is, that you can only use forward declared classes by using pointers and references and not by value, which may be a bit confusing if you are used to Java/C#.

Here is a simple example:
Say you have a base class "MyBaseClass" which internally (private) uses some helper class and another class that inherits from MyBaseClass. If you include the helper-class in your header like this:

[source lang="cpp"]// file MyBaseClass.h#include "SomeHelperClass"class MyBaseClass{public: // whater is neededprivate: SomeHelperClass myImplementationHelper;}// file MyDerivative.h#include "MyBaseClass.h"class MyDerivative : public MyBaseClass{public: ... // whatever you need}[/source]

If you have changes in SomeHelperClass.h the compiler will of course recompile MyBaseClass which directly uses the helper. But since you indirectly include SomeHelperClass.h also in MyDerivative this will also be recompiled even if MyDerivative has not changed at all. So you compile three cpp files instead of only two. Would you use a forward declaration of SomeHelperClass in your base class and only include the header in MyBaseClass.cpp, you would only need to compile two.

I hope this helps.

edited some typos

Edited by doeme, 08 August 2012 - 04:12 AM.


#9 Álvaro   Crossbones+   -  Reputation: 12504

Like
1Likes
Like

Posted 08 August 2012 - 05:00 AM

Alrigth, forward declaration starts to make sense.
Then I have one last hassle, why do you put your includes in the .cpp files? The Headers can compile without any other classes now, but the body cannot. Is there an upside/downside?


Generally include directives should be in the .cpp file only, if at all possible. Perhaps this is easier to illustrate with an example.

Say you have a class `AI_Agent' that has a method `pick_action'. Picking an action in this particular game involves using a GOAP planner, but this fact is not part of the interface of AI_Agent. So we'll include GOAP_Planner from AI_Agent.cpp, but not from the header file. If you were to put that include directive in the header file, any module that includes AI_Agent.h would have to compile GOAP_Planner.h, and would need to be recompiled if GOAP_Planner.h were changed.


The AI_Agent could keep a pointer to the GOAP_Planner it's using and that would have to be reflected in the class{...} block, which is in the header file. In that case, a forward declaration will allow for the use of the pointer, and users of AI_Agent have no need to know the details of that class.




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