1

I'm currently reading C++ Primer and am at the point of class friends and member function friends and I'm having trouble figuring out how to get the code that has the following pseudoform to work:

class B;

class A {
public:
    A(int i): someNum(i) { }
private:
    int someNum;
    friend void B::someMemberFunction(Args); // Compile error: Incomplete Type
};

class B {
public:
    void someMemberFunction(Args) { /* doStuff */ }
private:
    vector<A> someVector { A(5) };
};

If you try to compile in this form it gives the incomplete type error on the friend line. So the solution is to move the class B definition above class A:

class A;

class B {
public:
    void someMemberFunction(Args) { /* doStuff */ }
private:
    vector<A> someVector { A(5) }; // Compile error: Incomplete Type
};

class A {
public:
    A(int i): someNum(i) { }
private:
    int someNum;
    friend void B::someMemberFunction(Args);
};

However now on the vector line, it doesn't know how to create an object of type A, since A has yet to be defined. So then A needs to be defined before B. But now we've arrived back at the original problem. I think this is called circular dependency? I don't know how to fix this with forward declarations.

Any help would be appreciated. Thanks.

Wallboy
  • 154
  • 5
  • 14
  • This would help you. http://stackoverflow.com/questions/4816698/avoiding-circular-dependencies-of-header-files – Watz Apr 25 '14 at 02:50
  • 1
    My advice would be to resdesign your classes so that the problem goes away. – M.M Apr 25 '14 at 05:09

1 Answers1

0

I think you will either have to make the whole of class B a friend (which removes a dependency in A anyway so it's probably a good thing), or use a constructor instead of the in-class initializer.

class B;

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

class B {
public:
    void someMemberFunction() { /* doStuff */ }
private:
    vector<A> someVector { A(5) };
};

Or this

class A;

class B {
public:
    B();
    void someMemberFunction() { /* doStuff */ }
private:
    vector<A> someVector;
};

class A {
public:
    A(int i): someNum(i) { }
private:
    int someNum;
    friend void B::someMemberFunction();
};

B::B(): someVector{A(5)} { }
user657267
  • 20,568
  • 5
  • 58
  • 77
  • The vector isn't a function though. Just a data member. Or does this not matter? Edit: Oh i see, you're turning it into a function that creates the vector. – Wallboy Apr 25 '14 at 02:49
  • Sorry didn't realize you wanted a data member. I don't think this is possible, if you want to keep the in-class initializer you will have to make the whole of `class B` a friend (which may make more sense as limiting the `friend`ship to a single member function creates a dependency), otherwise you will have to remove the initializer for `someVector` and use a constructor with an initializer list, but defined below the definition of `A`. – user657267 Apr 25 '14 at 02:57