8

Is there any way around this:

class B;

class C { 
 public:
  C() { }
 private:
  int i;
  friend B::B();
};

class B { 
 public:
  B() { }
 private:
  int i;
  friend C::C();
};

Gives error:

prog.cpp:8: error: invalid use of incomplete type ‘struct B’
prog.cpp:1: error: forward declaration of ‘struct B’
jparthj
  • 1,606
  • 3
  • 20
  • 44
BCS
  • 75,627
  • 68
  • 187
  • 294
  • I think the closest you can get is `friend class B` – Seth Carnegie May 28 '11 at 00:20
  • 1
    What exactly did you want to do that you needed the constructor of B and C to be visible to each other? – Mike Bailey May 28 '11 at 00:26
  • @Mike, that is actually a synthetic example. The real situation is that, for reason to complicated to go into, I can't allow a dependency on C to force a dependency on the the definition of B. – BCS May 28 '11 at 01:55

4 Answers4

5

You just can't do this. Remove the circular dependency.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • You can grant friendship to the whole class recursively, just not to individual members. – Nemo May 28 '11 at 00:23
3

According to IBM's documentation (which I realize is not normative):

A class Y must be defined before any member of Y can be declared a friend of another class.

So I think the answer is "no".

Of course, you can use

friend class B;

...instead of friend B::B(), but that grants friendship to all of B's members. And you probably already knew that.

Nemo
  • 70,042
  • 10
  • 116
  • 153
2

Since you're very selective about friendship (access to specific member functions given to specific classes), the Attorney-Client Idiom may be what you need. I'm not sure how well this will work with constructors, though.

Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
1

I realize that this is a really silly idea, but couldn't you—theoretically—accomplish this through inheritance, by making the parent class' constructors friends? The code compiles, at least, questionable though it may be.

class A {
 public:
  A() { }
 private:
  int i;
};

class D {
 public:
  D() { }
 private:
  int i;
};

class B : public A {
 public:
  B() { }
 private:
  friend D::D();
};

class C : public D {
 public:
  C() { }
 private:
  friend A::A();
};
Chris Frederick
  • 5,482
  • 3
  • 36
  • 44
  • 3
    I think friendship can't be inherited ... C is not a friend of B and B it not a friend of C here ... – Thomas Vincent May 28 '11 at 00:43
  • Friendship definitely is not inherited. – Nemo May 28 '11 at 01:05
  • True. But if you just wanted to give the constructors access to private variables, this would make the private data in B and C accessible to the constructors of B and C's parent classes—which can be respectively called by B and C's constructors—even though B and C cannot access each other's private data directly. – Chris Frederick May 28 '11 at 01:07