1

I have 4 classes, A, A1, B, and B1. class A contains a private nested class A1, and class B contains a private nested class B1. I want the constructor for class B::B1 to have access to the private data members of objects of type A::A1. My solution for this was to use the keyword 'friend'. I'm having trouble getting mutual friendship between the outer classes to work, however, and online guides don't account for friendship between two private, nested classes.

The plan is to make B a friend of A so B1 knows about A1. Then make A a friend of B so A1 knows about B1. Then make B1 a friend of A1 so B1 can access the private data members of A1. Here is some code that fails to do that. You can feel free to ignore it.

    //A.h
    #pragma once
    #include "B.h"
    
    class A {
        friend class B;
    private:
        class A1 {
            friend class B::B1;
        private:
            int num = 3;
        };
        A::A1 a1;
    }
    //B.h
    #pragma once

    class A;
    
    class B {
        friend class A;
        //stuff
    private:
        class B1;
    public:
        B1& b; // I would prefer this to not be a reference
        B(A a); // Error: incomplete type
    };
    // B.cpp
    #include "B.h"
    #include "A.h"
    
    class B::B1{
        B::B1(A::A1 a1) {
            int num = a.num;
        };
            int num;
    };
    B::B(A a) : b(a.a1) {}

There appear to be many errors with this code, but there were many different kinds of errors in all of my attempts to get this to work. An explanation of these errors would be helpful, but I'm seeking a working example of how to get the friendships and forward-declarations right.

mana
  • 545
  • 4
  • 12
  • Does this answer your question? [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) –  Aug 13 '20 at 02:40
  • BTW: In case my above comment wasn't clear, the problem isn't necessarily the `friend` declarations themselves, but rather that you have a circular dependency. Once you get that straightened out, the friendship problem should fall into place. –  Aug 13 '20 at 02:47
  • @Chipster no it does not. The problem I present is more complicated than that example and I have been unable to extend the ideas from that post to my own problem. – mana Aug 13 '20 at 02:48
  • Also, just for future reference, it's always helpful to have the exact errors you want an explanation for verbatim in your question. Otherwise, it's very hard to truly understand how to properly help you. –  Aug 13 '20 at 02:49
  • Have you tried using a [forward declaration](https://stackoverflow.com/q/4757565/10957435) instead of including both .h files? –  Aug 13 '20 at 02:52
  • By including both .h files, you're creating a circular dependency. –  Aug 13 '20 at 02:52
  • 1
    @Chipster You can't forward declare private, nested classes. I don't even think you can forward declare nested classes. – mana Aug 13 '20 at 02:55
  • You can too forward-declare nested classes. Just simply `class Outer { class Inner; }; class Outer::Inner { ... };` – Igor Tandetnik Aug 13 '20 at 03:04
  • @mana To be honest, I jumped the gun and didn't realize they were nested classes at first. If the classes weren't nested, I'm certain it would be possible. However, answering the question about nested classes is above my skill level. That is where I tap out and up-vote your question instead –  Aug 13 '20 at 03:04
  • I don't think you can pull that off. You'd need to move either `A1` or `B1`, or both, to the namespace level, so they can be forward-declared (independently of `A` and `B`). You can name them, say, `A_A1` and `B_B1`, and then within `A` have `using A1 = A_A1;` so most of the code can continue to refer to `A::A1` (and similarly with `B::B1`) – Igor Tandetnik Aug 13 '20 at 03:14
  • @LouisGo conceptually it definitely makes sense for them to be nested. I think I can see how I could get the application to work without nesting, but it would screw up the nice encapsulation. Removing nesting would be a work-around. – mana Aug 13 '20 at 03:14
  • @IgorTandetnik to your first response, do you agree that you can't forward declare A::A1 in B.cpp? – mana Aug 13 '20 at 03:18
  • 1
    You can forward-declare `A::A1`, but only within the full definition of `A`; you can't forward-declare both `A` and `A1`. The problem is that, for `A1` to declare `B::B1` a friend, it needs to see at least forward-declaration of `B1`, which requires full definition of `B`, which requires full definition of `B1` because you want `B` to have a `B1` data member. At which point you've painted yourself into a corner. – Igor Tandetnik Aug 13 '20 at 03:23
  • since removing the nesting would be really really bad for the encapsulation of my program, I'm also open to other recommended solutions that use something besides the 'friend' keyword. – mana Aug 13 '20 at 03:59

0 Answers0