Home > Mobile >  Why C friendship for function inside a class does not work same as a standalone function?
Why C friendship for function inside a class does not work same as a standalone function?

Time:08-08

I want to know why one of the following two codes compiles while the other does not. In the first code, createB is a stand alone function. In the second code the function createB is a member of class A.

The first one compiles.

#include <iostream>

class A;

class B {
public:
  B() { std::cout << "B"; }
  friend B createB();
};

class A {
public:
  A() { std::cout << "A"; }

};

B createB() { return B(); }

int main() {
  A a;
  B b = createB();
}

The second one does not.

#include <iostream>

class A;

class B {
public:
  B() { std::cout << "B"; }
  friend B A::createB();
};

class A {
public:
  A() { std::cout << "A"; }

  B createB() { return B(); }
};

int main() {
  A a;
  B b = a.createB();
}

CodePudding user response:

Case 1

In the first snippet, createB is a free(standalone) function and it is not mandatory that the friend declaration names an existing function. So this works and also implicitly declares a function named createB with return type of B in the global namespace, though this createB is not visible through ordinary lookup.

Case 2

The problem in the 2nd example is that A is an incomplete at the point of the friend declaration friend B A::createB();.

To solve this, we can move the definition of A to before B so that A is complete at the point of the friend declaration. Additionally, we can provide the definition of createB after B has been defined as shown below:

//forward declaration so that B can be used in declaration B createB();
class B;

class A {
public:
  A() { std::cout << "A"; }
  //this is declaration
  B createB();
};

class B {
public:
  B() { std::cout << "B"; }
  friend B A::createB();    //this works as now at this point A is complete since we moved the definition of A to before B
};

//this is definition 
B A::createB() { return B(); }
int main() {
  A a;
  B b = a.createB();
}

Working demo

  • Related