I've recently discovered that it is bad form to have #include
s in your header files because anyone who uses your code gets all those extra includes they won't necessarily want.
However, for classes that have member variables defined as a type of another class, what's the alternative?
For example, I was doing things the following way for the longest time:
/* Header file for class myGrades */
#include <vector> //bad
#include "classResult.h" //bad
class myGrades
{
vector<classResult> grades;
int average;
int bestScore;
}
(Please excuse the fact that this is a highly artificial example)
So, if I want to get rid of the #include
lines, is there any way I can keep the vector
or do I have to approach programming my code in an entirely different way?
If your class directly includes a data member of a given type (and not, by the way, a pointer to that type or a reference to that type), then you must have the class declaration available so that the compiler knows how many bytes an instance of your object takes up. This usually means that you have to #include
the header files.
However, there are techniques known as compiler firewalls that can let you structure classes in a way that gives the class access to objects of the appropriate type without directly including them. One of these is the pImpl idiom, in which your class implementation looks like this:
class MyClass {
public:
/* ... */
private:
struct Impl;
Impl* pImpl;
};
Here, you forward-declare a struct Impl
containing your class's implementation, then store a pointer to the Impl
struct in the class. Since having a pointer in your class doesn't require the size of the object being pointed at to be known, this is perfectly fine. Then, in the .cpp file, you can define the Impl
struct:
struct MyClass::Impl {
/* ... */
};
and you can implement all of the class's member functions by just following the pImpl
pointer to the actual fields. This has the drawback that all field accesses require a pointer indirection, but the ability to change the class implementation so quickly does make this useful.
Another option along the same lines is to make the class an abstract base class, then to provide a static factor function that returns an object subclassing your base class that actually contains the implementation. For example:
class MyClass {
public:
virtual ~MyClass(); /* Need virtual dtors in polymorphic classes! */
virtual void doSomething() = 0;
/* ... etc. ... */
static MyClass* New(/* ... args ... */);
};
Then, in the .cpp file you can define a concrete subclass of MyClass
that actually does all the work:
class ActualClass: public MyClass {
public:
void doSomething();
/* ... etc. ... */
private:
/* ... data members ... */
}
and finally, implement New
to create a new instance of the implementation class:
MyClass* MyClass::New(/* ... args ... */) {
return new ActualClass(/* ... args ... */);
}
Hope this helps!
There is absolutely nothing wrong with including other headers in your header.
You need to be sure that your header includes all of the headers that it depends upon and you should avoid including extraneous, unneeded headers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With