tags:

views:

360

answers:

4

What is the proper layout of a C++ .h file?

What I mean is header guard, includes, typedefs, enums, structs, function declarations, class definitions, classes, templates, etc, etc

I am porting an old code base that is over 10 years old and moving to a modern compiler from Codewarrior 8 is proving interesting as things seem all over the place. I get a lot of dont name a type errors, forbidding declaring without a type, etc, etc.

+3  A: 

There is no silver bullet regarding how to organize your headers. However one important rule is to keep it consistent across the project so that all persons involved in the project know what to expect.

Usually typedefs and defines are at the top of the file in my headers, but that can not be regarded as a rule, then come class/template definitions.

A rule that I follow for C++ is one header per class, which usually keeps the headers small enough to allow grasping the content and finding things without scrolling too much.

Dan Cristoloveanu
A: 

I think best thing you can do is to check out layout of any library files.

Ashish
+1  A: 

It depends on what you mean by proper. If you mean language-enforced, there really isn't one. In fact, you don't even have to name it ".h". I've seen ".c" files #include'd in working commercial code (name withheld to protect the guilty). #include is just a preprocessor hack to get some kind of rough modularity in the language by allowing files to textually include other files. Anything else you tend to see as standard practice is just useful idioms people have developed over time.

That doesn't help your current issue though.

I'd guess that what you are actually seeing is a lot of missing symbols due to platform differences. Nothing due to weirdly-formed .h files at all.

It is possible that the old code was written to work with an old K&R-style C compiler. They had oddities like implicit function declarations (any reference to an undeclared routine assumed it returned int and all its parameters were int). You could try seeing if your compiler has a K&R flag, but a lot of the flagged stuff may actually be latent errors in the old code.

T.E.D.
A: 

It sounds like you're running into assumptions made based on the previous implementation (Codewarrior). For example:

#include <iostream>
int main() {
  std::cout << "string literal\n";
  return 0;
}

This relies on iostream including something it's not required to declare: the operator<<(ostream&, char const*) overload (it's a free function, not a method of ostream like the others). And to be completely unambiguous, #include <ostream> is also required above. In C++, library headers are allowed to include any other library header, in general, so this problem crops up whenever someone inadvertently depends on this.

(That the extra header is required in this particular circumstance is considered a flaw by many, including me, and almost all implementations do provide the declaration of this function in iostream. It is still the shortest, common example I know of to illustrate this.)

It's often more subtle and complicated than this simple example, but the core issue is the same. The solution is to check every header to make sure it includes any libraries it requires, starting with the ones giving you the errors. E.g. #include <vector> and make sure you use std::vector (to avoid relying on it being in the global namespace, which is done in some, mostly old and obsolete now, implementations) when you get "vector does not name a type".

You might also be running into dependent types, in which case you'd add typename.

Roger Pate