0

I'm trying access a friend's method as defined the following. I have 4 files. Two header:

Header a.h:

#include "b.h"

class A
{
public:
    A();
    ~A();
    void testStuff(int i);
};

Header b.h:

#include "a.h"

class A;

class B
{
    friend class A;

public:
    B();
    ~B();
    friend void doStuff(int i);
};

And two including some code, a.cpp:

#include "a.h"

void A::testStuff()
{
    B b {B()};
    b->doStuff(1);
}

b.cpp:

#include "b.h"

void B::doStuff(int i)
{
    m_stuff = i;
}

If I remove the keyword friend everything works fine. But if I declare doStuff() as a friend, I get the following error:

error: ‘class B’ has no member named ‘doStuff’

I tried following this tutorial. What do I miss?

q9f
  • 11,293
  • 8
  • 57
  • 96

3 Answers3

4

Your understanding regarding friend function is wrong. If you declare a function friend to another class, it means the friend function can access private members of that class, it does not mean the friend function becomes a class member.

Here doStaff() is friend to B, not a member of B. But you are using it on an object of B, hence compiler saying that it is not member of that class. using friend gives doStaff permission to access B's private members in it.

The tutorial you are following says it clearly. duplicate() method is a friend to Rectangle, hence it can access the private members width and height, but duplicate() is not used as a class method of Rectangle.

In summary, your question is wrong. You can access a friend function just like any free (non-class method) function. The question is how friend functions accesses the member of a class to which it is friend, and as said, it can access everything in that class, which is the motivation of having friend functions, namely to give access of private members of a class to a outsider.

Similarly a friend class can access everything of the class to which it is friend.

So for your problem, either you remove friend from doStaff to make it a member of B. But I guess your intention was to use friend method, in that case you can do the following:

void doStuff(B b, int i)
{
  b.m_stuff = i; // it is friend function of B, so can access m_staff
}

or you can make doStaff() member of A and then you can write

class A{
  //other members
  void doStaff(B& b, int i){ b.m_staff=i;}

void A::testStuff() {

  B b {B()};
  doStuff(b,1); //although u can just write "b.m_staff = 1;" right here
}
Rakib
  • 7,435
  • 7
  • 29
  • 45
  • Now I got it. I thought I can use the friend's private methods, but accessing it's members is even more comfortable. Thanks. – q9f Jun 06 '14 at 19:31
3

There would be no point to declare methods in your own class as "friend". Therefore, a friend declaration like

friend void doStuff(int i);

inside class B doesn't actually declare a member function of class B (it's family, you don't need to make it a friend), it declares a global function named doStuff. You could write

friend void A::doStuff(int i);

which means "If there is a class named A somewhere, and it has a member named doStuff with an int parameter, then that member function is a friend". What you wrote was "if there is a global function doStuff (int i) somewhere, then that function is a friend".

So you haven't declared B:doStuff (int i) in your class, and implementing the function very sensibly gives an error.

And if you want A::testStuff() to be allowed to call doStuff, you should add in class B:

friend void A::testStuff ();
gnasher729
  • 51,477
  • 5
  • 75
  • 98
1

You declared doStuff() as a member of class B, when you did "void B::doStuff(int i)", but the friend keyword applies to non-member functions. It's basically there to make it so that a function that is not a member of a class can access that class's private members.

BTW, B has class A declared as a friend, which means a function that you declare in A can access private members in class B.

As you can see, there's a difference between declaring friend classes and friend functions.

Tom
  • 11
  • 1