Search code examples
c++inner-classesforward-declaration

Defining a nested class out of line in C++


Sorry if this has been asked before; I found similarly titled questions, but none of them focused on the same aspects I'm having trouble with.

There's a class A, and a class B that should only be accessible from A. I think nesting B inside A will achieve that, but I'm struggling with the logistics.

A has a B as a member. As such, not defining B prior to declaring A's members causes incomplete type errors. I thought I'd get around this by declaring A, defining A::B, then defining A, but that just throws the same errors plus incomplete type 'A' in nested name specifier.

class A;

class A::B
{
    ...
};

class A
{
private:
    class B;
    B b;
    ...
};

The only functional examples I can find would put B's member declaration directly inside A's, which I'd really like to avoid doing: B's header information is several times longer and much denser than A's. Splitting the two up into separate files would be best, but actually nesting them inline is incredibly unwieldy.

Fallback options at this point include making A's B a pointer (no real reason why not, but is this really something that can't be done?) and leaving them as independent classes. But surely this can't be that hard?

What do I need to declare to link these properly and in what order?

I am not particularly knowledgeable about the depths of C++ so please explain like I'm five and refrain from shaming me into the ground for not knowing everything.


Solution

  • One particularly non-convoluted way of doing this would be

    class B
    {
       friend class A;
       private:
        // everything;
    };
    
    class A
    {
      B b;
    };
    

    This of course makes all the guts of B accessible to A, bit if B is such A-specific, it should not be a problem.

    If this is not desirable, a slightly wore windy path to a solution would be

    class PreA
    {
       protected:
          class B { ... };
    };
    
    class A : PreA
    {
       B b;
    };