I do not speak much English, sorry. When I read c primer, I meet this code.
class Message {
friend class Folder;
public:
...
private:
std::string contents;
std::set<Folder*> folders;
...
};
...
void swap(Message& lhs, Message& rhs) {
using std::swap;
for (auto f : lhs.folders) { f->remMsg(&lhs); }
// class Folder is undefined by book
...
}
...
I have omitted functions that I think are irrelevant. Besides, c primer asks me to implement class Folder
by myself. So I add more code.
class Folder; // my code
class Message {
friend void swap(Message&, Message&); // my code
friend class Folder;
public:
...
private:
std::string contents;
std::set<Folder*> folders;
...
};
void swap(Message&, Message&); // my code
// I added the whole class
class Folder {
friend void swap(Folder&, Folder&);
friend class Message;
public:
...
private:
...
void addMsg(Message* m) { msgs.insert(m); }
void remMsg(Message* m) { msgs.erase(m); }
};
void swap(Folder&, Folder&); // my code
In file.cpp
void swap(Message& lhs, Message& rhs) {
using std::swap;
for (auto f : lhs.folders) { f->remMsg(&lhs); }
// In vs2019
// Error (active) E0265 function "Folder::remMsg" is inaccessible
...
}
As you can see, I can't use the function Folder::remMsg
.
Then, I try to figure out how friend function works. I write these codes.
struct B; // This is [line 1]
struct A {
friend void swap(A&, A&);
private:
int n;
std::vector<B*> Bs;
};
void swap(A& lhs, A& rhs) {
for (auto f : lhs.Bs) { f->n; }
// f->n is still inaccessible
// If I delete line 1, the code can be compiled successfully
// same with class Folder
...
}
struct B {
friend struct A;
private:
int n;
A C;
};
I don't understand why does this happen.
By the way, the reason I declare class Message
and class Folder
friend class with each other is I want symmetric swap
to use copy-swap.
CodePudding user response:
void swap(Message& lhs, Message& rhs)
is a friend of Message
, but you try to access private members of Folder
. Your last code has the same issue: friend void swap(A&, A&);
is a friend of A
but you try to access private members of B
. friend
is not transitive. Just because A
is friend of B
and swap
is a friend of A
does not mean swap
is a friend of B
.
If you want void swap(A&,A&)
grant access to private member of B
then make it a friend of B
:
#include <vector>
struct B;
struct A {
friend void swap(A&, A&);
private:
int n;
std::vector<B*> Bs;
};
struct B {
friend void swap(A&,A&);
private:
int n;
A C;
};
void swap(A& lhs, A& rhs) {
for (auto f : lhs.Bs) { f->n; }
// ^^ access private member of A
//^^ access private member of B
}