Reducing #includes with Forward Class Declarations

Problem

You have a header file that references classes in other headers, and you need to reduce compilation dependencies (and perhaps time).

Solution

Use forward class declarations where possible to avoid unnecessary compilation dependencies. Example 2-4 gives a short example of a forward class declaration.

Example 2-4. Forward class declaration

// myheader.h
#ifndef MYHEADER_H_ _
#define MYHEADER_H_ _

class A; // No need to include A's header

class B {
 public:
 void f(const A& a);
 // ...
 private:
 A* a_;
};

#endif

Somewhere else there is a header and perhaps an implementation file that declares and defines the class A, but from within myheader.h I don't care about the details of A: all I need to know is that A is a class.

Discussion

A forward class declaration is a way to ignore details that you don't need to be concerned with. In Example 2-4, myheader.h doesn't need to know anything about the class A except that it exists and that it's a class.

Consider what would happen if you #included the header file for A, or, more realistically, the header files for the half-dozen or so classes you would use in a real header file. Now an implementation file (myheader.cpp) includes this header, myheader.h, because it contains the declarations for everything. So far, so good. If you change one of the header files included by myheader.h (or one of the header files included by one of those files), then all of the implementation files that include myheader.h will need to be recompiled.

Forward declare your class and these compilation dependencies go away. Using a forward declaration simply creates a name to which everything else in the header file can refer. The linker has the happy task of matching up definitions in the implementation files that use your header.

Sadly, you can't always use forward declarations. The class B in Example 2-4 only uses pointers or references to A, so I can get away with a forward declaration. However, if I use an A member function or variable, or if I have an object of type A--and not just a pointer or reference to onein my definition for the class B, suddenly my forward declaration is insufficient. This is because files including myheader.h need to know the size of B, and if A is a member variable of B, then the compiler needs to know A's size to figure out B's size. A pointer or a reference to something is always the same size, so in the case where you are using pointers or references, the details of A aren't of interest to the compiler and therefore A's header file isn't necessary.

Not surprisingly, if you include any definition in myheader.h that uses members of A, you have to #include A's header. This is because the compiler needs to check the function signature of the A member function or the data type of the A data member you are referencing. To illustrate, this code requires an #include:

#include "a.h"

class B {
 public:
 void f(const A& a) {
 foo_ = a.getVal( ); // Have to know if a.getVal is valid
 }
// ...

In general, use forward declarations when you can to reduce the amount of #include-ing that goes on at compile time.

Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index



C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net