3
#include <iostream>
using namespace std;

class A;

class B {
public:
    A createA();
};

class A {
private:
  A() {
      cout << "A Object created" << endl;
  }

  friend A B::createA();
};

A B::createA() {
    A a_obj;
    return a_obj;
}

int main(int argc, char* argv[]) {
    B b;
    A a = b.createA();
}

This code above works properly!

But I have the following questions:-

  1. I tried swapping the position of class A and class B but it produced an error saying that A::A() is inaccessible and trying to access incomplete type class B Why?
  2. Can anyone help me understand what is happening when you write friend A B::createA(); is it trying to access the definition of createA() immediately.
pmtatar
  • 353
  • 2
  • 7

1 Answers1

4

This problematic part is the B::createA.

Here you are 'reaching into' type B to pull out its member function createA. In order to do that, you need to know the complete type B. Otherwise, how would the compiler know where to find that member function, or if it even exists?

For the purpose of declaring a friend member function this would not be necessary from a strictly technical point of a compiler implementation. After all, you don't do any function call at this point, so there's nothing to resolve here. But it would still be problematic, as I could also write B::thisfunctiondoesnotexist instead, and the compiler would have to accept it as well. Therefore the language chooses to require that the full type is known beforehand whenever you use :: to pull out some of its innards.

One easy way to work around this limitation (if for instance you need to avoid cyclic dependencies between classes) is to put the functionality of createA into a free function instead of a member function. A free function relying on both A and B can still be declared if the types have only been forward-declared at that point, but not defined.

ComicSansMS
  • 51,484
  • 14
  • 155
  • 166
  • I am trying to do the same with a (friend) free function, but somehow I get that the private constructor is inaccessible, I'm trying to figure out why... – Antonio May 11 '23 at 14:37
  • ... And the reason was that in the friend function I was using make_unique, which is not friend of my class so it cannot call the constructor. Solution available [here](https://stackoverflow.com/questions/65286678/make-unique-cannot-access-private-constructor-in-static-member) – Antonio May 11 '23 at 15:23