Including headers inside class declaration / definition
I've never seen this inside a class and would recommend you to never do it if you want to still understand the code the other day.
That said, there is a case where I find this technique acceptable and that is when you have a large table from which you need to generate multiple constructs like an enum and an attribute table. Let's have two files like:
foobars.h:
enum Foobars {
#define FOOBAR(id, description, args) FOOBAR_##id,
#include "foobars.tab"
#undef FOOBAR
};
extern const char *foobar_names[];
const char *parse_foobar(Foobars fb, const char *input);
foobars.cpp:
#include "foobars.h"
const char *foobar_names[] = {
#define FOOBAR(id, description, args) description,
#include "foobars.tab"
#undef FOOBAR
};
const char *parse_foobar(Foobars fb, const char *input) {
switch(fb) {
#define INT get_int(&input)
#define FLOAT get_float(&input)
#define STRING get_string(&input)
#define FOOBAR(id, description, args) args
#include "foobars.tab"
#undef FOOBAR
}
return input;
And the magic is in "foobars.tab" (it's special, so I recommend not calling this anything.h or anything.hpp or any other common suffix):
/* CAUTION! This file is included using C preprocessor in the middle of various structures
* It must not contain anything except definitions of foobars in the FOOBAR macro and
* comments. Don't forget NOT to write semicolons; some of the structures are
* comma-separated and some semicolon-separated. FOOBAR will be defined appropriately before
* including this file. */
FOOBAR(NULL, "Empty command, does nothing", {}) // NO semicolon!
// Also some preprocessors don't like empty arguments, so that's why {}.
// (void)0 is an alternative.
FOOBAR(FOO, "Foo bars and bazes", a = INT; b = STRING)
FOOBAR(BAR, "Bars, but does not baz", x = FLOAT)
...
The other option is defining a macro to content of the special include. If the table is short, the macro is easier to read, but if the file is long, the special file makes more sense.
The last option is to have the table in altogether different format and generate the code, but that involves writing some special script for building it and this does not.
The preprocessor (which runs before anything), when it stumbles upon an include
, almost literally copies the content of that header and pastes it in the place of the #include
directive.
The advantages of using it like you describe are few, the main one being that you don't have to duplicate code.
However, in 9999/10000 situations, it is definitely not worth the hassle. If you have a typo somewhere in the header file, you'll get strange errors in every file that uses it, and it's not clear at all what it's doing until you actually open the file and read it.
Avoid that if at all possible. I can't think of a situation where it would be absolutely necessary; the same effect can be achieved with inheritance or composition most of the time without all the side-effects.
In languages like Ruby this concept is known as Mixin. Since we have multiple inheritance in C++, we don't need it here.