Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including headers inside class declaration / definition

Tags:

c++

I know you can do something like:

def.h:

A();
int x;

A.h

class A
{
public:
#include "def.h"
}

A.cpp

A::A()
{
    x = 0;
}

int main()
{
    A a;
    return 0;
}

My questions is: why would you do this? Are there any advantages? I can see how it would be helpful if you have some classes with the same members but not the same base, but is it worth the hassle? It's not very readable, is it? Also, how does the compiler treat these includes? Does it just paste the content of the header where it's included (kind of like a macro)?

like image 656
Luchian Grigore Avatar asked Sep 08 '11 11:09

Luchian Grigore


People also ask

How do you define a class in a header?

Traditionally, the class definition is put in a header file of the same name as the class, and the member functions defined outside of the class are put in a . cpp file of the same name as the class. Now any other header or code file that wants to use the Date class can simply #include "Date. h" .

What is a class header in C++?

The header file contains the definitions for the types and names of members, methods, and how the class relates to other classes (if it does). ▪ The source file contains the code that implements the functionality of the class. ▪ Sometimes there is a header file for a class but no source file.

Why do we use header files in C++?

Why Do You Use Header Files? Header files are used in C++ so that you don't have to write the code for every single thing. It helps to reduce the complexity and number of lines of code. It also gives you the benefit of reusing the functions that are declared in header files to different .

HOW include all header files in C++?

You make the declarations in a header file, then use the #include directive in every . cpp file or other header file that requires that declaration. The #include directive inserts a copy of the header file directly into the . cpp file prior to compilation.


2 Answers

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.

like image 185
Jan Hudec Avatar answered Sep 20 '22 01:09

Jan Hudec


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.

like image 24
Seth Carnegie Avatar answered Sep 18 '22 01:09

Seth Carnegie