1

I'd like to have includes just in .cpp files, as I'm working in a project with lots of classes which will have to interact with each other, and I feel it's a bit better since you don't have to worry for what you have already included or not, I just don't know well how to do it; here's an example:

#include "UnitConverter.hpp"
#include <string>
//extern namespace std;
//extern class  std::string;
//extern class UnitConverter;
//extern enum UnitConverter::UnitTypes;
//extern enum UnitConverter::UnitSystem;
//extern enum UnitConverter::ScalingType;

class AnalogOutput{

    public:
    std::string name;
    UnitConverter::UnitTypes unit_type;
    UnitConverter::UnitSystem unit_system;
    UnitConverter::ScalingType scaling_type;
}

how would I declare the namespaces, classes and enum types so that compiles without the includes in the hpp file but in the cpp file?

heczaco
  • 198
  • 1
  • 13
  • 3
    It is not clear to me why do you want to do that. – Jan Henke Aug 25 '16 at 14:33
  • 4
    why are you worried about "what you have already included or not" ? Just include what you need, if you include the same header twice, thats what include guards are good for. – 463035818_is_not_an_ai Aug 25 '16 at 14:34
  • 1
    you could alternatively forward declare everything and only use pointers and references. But having a sorted include system with each class having their own header seems clearer and makes less headaches. Afterwards you can also use some tools to check for unused includes in case you have too much. – Hayt Aug 25 '16 at 14:40

3 Answers3

6

You can achieve this using a header you include everywhere that itself includes everything you need.

Using a catch-all header will kill compile time. Badly. Don't. Do. It.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
2

It sounds like you're asking about using forward declarations. To do that the syntax is simply class MyClass; (you don't need those extern prefixes).

And to forward declare a class which resides in a namespace, wrap your forward declaration in the namespace:

namespace MyNamespace {
    class MyClass;
}

However, there are at least two big caveats here relevant to your code snippet:

  1. You can only make use of pointers or references to the forward declared type. Thus, in your example you won't be able to forward declare std::string if you want to have a std::string member in your AnalogOutput class - you'd have to change that member to be a pointer or reference instead.
  2. You can't forward declare nested types. So you won't be able to forward declare those enums because they are all nested within UnitConverter.
Community
  • 1
  • 1
atkins
  • 1,963
  • 14
  • 27
2

std::string will make it difficult for you, as it is a typedef to a template... Better do not worry about that one - it is extremely unlikely that you would get circular includes with the system headers...

For your project's classes, you will have to declare them exactly as they have been declared in their corresponding header:

// Example.h
namespace Dummy
{
    class Example { /* ... */ };
}

And then to avoid includes:

// Test.h
namespace Dummy
{
    class Example; // just the bare name!
}

But be aware that this way, you get incomplete types, and you cannot use them directly. You can use pointers or references to them, but the following composition won't work:

// Test.h
/* ... */
class Test
{
    Dummy::Example ex;    // type is incomplete!
    Dummy::Example& ex_r; // reference is OK
    Dummy::Example* ex_p; // pointer, too

    inline void foo()
    {
        // type incomplete; you cannot do this here:
        ex_p->bar();
        // needs to be done in cpp file where Example.h is included instead
    }
};
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • Upvote for difficulty of forward declaring `std::string` - which I did not think of myself... :) – atkins Aug 25 '16 at 15:08
  • yep, thanks a lot guys, I think I'll leave the needed includes on the hpp files and just be careful. @atkins – heczaco Aug 25 '16 at 15:16