0

I try to access a private member data of class X, with a friend function, which itself is a member function of class A.
Here's the code:

class X {
    int foo;
public:
    friend void A::func(X x1);
};

class A {
public:
    void func(X x1) { x1.foo = 999; }
};

This won't compile for the reason:
Error C2248 'X::foo': cannot access private member declared in class 'X'

I tried changing the order, declaring A before X, but it didn't help..
What's causing this?

  • It doesn't compile because `A::func()` is not declared. But pls pls don't write such thing in production code all people will hate you. If it's to understand what friend is doing it's okay... but you alost never needs that... The most pratical thing I saw is when you need to implement `operator<<` and `operator>>`. Other cases are most probably bad code design – Elvis Dukaj Sep 15 '20 at 15:53
  • Unrelated, but note that `func()` is modifying a *copy* of whatever `X` object is passed to it. The original `X` object is not modified. If you want that, pass it by reference instead: `void func(X &x1)` – Remy Lebeau Sep 15 '20 at 17:36

3 Answers3

2

You have to split correctly declaration and definition, as you have circular dependency:

class X;

class A {
public:
    void func(X x1);
};

class X {
    int foo;
public:
    friend void A::func(X x1);
};

void A::func(X x1) { x1.foo = 999; }

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
1

There's another error that you're ignoring. Namely:

error: 'A' has not been declared

You'll need to declare the class A with the function before you can reference it in X as a friend. However, the function takes an X, so you also need to declare X first!

It should look like:

class X;

class A {
public:
    void func(X x1);
};

class X {
    int foo;
public:
    friend void A::func(X x1);
};

void A::func(X x1) { x1.foo = 999; }
scohe001
  • 15,110
  • 2
  • 31
  • 51
0

You have to define the class A before the class X for example like

class X;

class A {
public:
    void func(X x1);
};

class X {
    int foo;
public:
    friend void A::func(X x1);
};

void A::func(X x1) { x1.foo = 999; }

Or instead of the forward declaration

class X;

you can use an elaborated type specifier like

class A {
public:
    void func(class X x1);
};

class X {
    int foo;
public:
    friend void A::func(X x1);
};

void A::func(X x1) { x1.foo = 999; }
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335