Forward Declaration of a Base Class

Tamara Wijsman picture Tamara Wijsman · Dec 23, 2008 · Viewed 15.7k times · Source

I'm trying to create proper header files which don't include too many other files to keep them clean and to speed up compile time.

I encountered two problems while doing this:

  1. Forward declaration on base classes doesn't work.

    class B;
    
    class A : public B
    {
    
        // ...
    }
    
  2. Forward declaration on STD classes doesn't work.

    namespace std
    {
        class string;
    }
    
    class A
    {
        string aStringToTest;
    }
    

How do I solve these problems?

Answer

Daniel Earwicker picture Daniel Earwicker · Dec 23, 2008

The first problem you can't solve.

The second problem is not anything to do with standard library classes. It's because you declare an instance of the class as a member of your own class.

Both problems are due to the requirement that the compiler must be able to find out the total size of a class from its definition.

However, the compiler can work out the size of a pointer to a class, even if it doesn't yet have the full definition of it. So a possible solution in such cases is to have a pointer (or reference) member in the consuming class.

Not much help in the base class case, because you won't get an 'is a' relationship.

Nor is it worth doing for something like std::string. Firstly, it's supposed to be a convenient wrapper around a character buffer, to save you from doing memory management on something so simple. If you then hold a pointer to it, just to avoid including the header, you're probably taking a good idea too far.

Secondly (as pointed out in a comment), std::string is a typedef to std::basic_string<char>. So you need to forward declare (and then use) that instead, by which time things are getting very obscure and hard to read, which is another kind of cost. Is it really worth it?