I'm trying to rewrite the program shown in the textbook (C Primer). This is small email-like program that contains two main Message
and Folder
classes. Source files are as below:
Folder.h
#pragma once
#include <set>
#include <string>
#include "Message.h"
using std::string;
using std::set;
class Folder {
friend class Message;
friend void swap(Folder&, Folder&);
public:
Folder(const string &fname):
name(fname) { }
Folder(const Folder&);
Folder& operator=(const Folder&);
~Folder();
void print_debug();
private:
string name;
set<Message*> msgs;
void add_to_Message(const Folder&);
void remove_from_Message();
void addMsg(Message*);
void remMsg(Message*);
};
Message.h
#pragma once
#include <string>
#include <set>
using std::set;
using std::string;
class Folder;
class Message {
friend class Folder;
friend void swap(Message&, Message&);
public:
// folders is implicitly initialized to the empty set
explicit Message(const string &str = ""):
contents(str) { }
// copy control to manage pointers to this Message
Message(const Message&);
Message& operator=(const Message&);
~Message();
// add/remove this Message from the specified Folder's set of messages
void save(Folder&);
void remove(Folder&);
void print_debug();
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void remove_from_Folders();
void addFldr(Folder*);
void remFldr(Folder*);
};
Folder.cc
#include <iostream>
#include "Message.h"
#include "Folder.h"
void swap(Folder &lhs, Folder &rhs) {
using std::swap;
lhs.remove_from_Message();
rhs.remove_from_Message();
swap(lhs.msgs, rhs.msgs);
swap(lhs.name, rhs.name);
lhs.add_to_Message(lhs);
rhs.add_to_Message(rhs);
}
Folder::Folder(const Folder &f):
msgs(f.msgs)
{
add_to_Message(f);
}
Folder::~Folder() {
remove_from_Message();
}
Folder& Folder::operator=(const Folder &rhs) {
remove_from_Message();
msgs = rhs.msgs;
name = rhs.name;
add_to_Message(rhs);
return *this;
}
void Folder::addMsg(Message *msg) {
msgs.insert(msg);
}
void Folder::remMsg(Message *msg) {
msgs.erase(msg);
}
void Folder::add_to_Message(const Folder &f) {
for (auto m : msgs)
m->addFldr(this);
}
void Folder::remove_from_Message() {
for (auto m : msgs)
m->remFldr(this);
}
void Folder::print_debug() {
std::cout << "Folder name : " << name << std::endl;
std::cout << "Messages : ";
for (const auto msg : msgs)
std::cout << msg->contents << " ";
std::cout << std::endl;
}
Message.cc
#include <iostream>
#include "Message.h"
#include "Folder.h"
Message::Message(const Message &msg):
contents(msg.contents), folders(msg.folders)
{
add_to_Folders(msg);
}
Message& Message::operator=(const Message &rhs) {
remove_from_Folders();
contents = rhs.contents;
folders = rhs.folders;
add_to_Folders(rhs);
return *this;
}
Message::~Message() {
remove_from_Folders();
}
void Message::save(Folder &f) {
folders.insert(&f);
f.addMsg(this);
}
void Message::remove(Folder &f) {
folders.erase(&f);
f.remMsg(this);
}
void Message::add_to_Folders(const Message &msg) {
for (auto f : msg.folders)
f->addMsg(this);
}
void Message::remove_from_Folders() {
for (auto f: folders)
f->remMsg(this);
}
void swap(Message &lhs, Message &rhs) {
using std::swap;
for (auto f: lhs.folders)
f->remMsg(&lhs);
for (auto f : rhs.folders)
f->remMsg(&rhs);
swap(lhs.folders, rhs.folders);
swap(lhs.contents, rhs.contents);
for (auto f : lhs.folders)
f->addMsg(&lhs);
for (auto f : rhs.folders)
f->addMsg(&rhs);
}
void Message::addFldr(Folder *f) {
folders.insert(f);
}
void Message::remFldr(Folder *f) {
folders.erase(f);
}
void Message::print_debug() {
std::cout << "Message content : " << contents << std::endl;
std::cout << "Exists in folders : ";
for (const auto f : folders)
std::cout << f->name << " ";
std::cout << std::endl;
}
main.cc
#include "Message.h"
#include "Folder.h"
int main() {
Folder f1("folder1");
Folder f2("folder2");
Message msg1("msg 1");
Message msg2("msg 2");
Message msg3("msg 3");
msg1.save(f1);
msg2.save(f1);
msg2.save(f2);
msg3.save(f2);
f1.print_debug();
f2.print_debug();
msg1.print_debug();
msg2.print_debug();
msg3.print_debug();
return 0;
}
When I try to compile these source files with command:
g main.cc Message.cc Folder.cc
It gives error:
Message.cc: In function ‘void swap(Message&, Message&)’:
Message.cc:49:23: error: ‘void Folder::remMsg(Message*)’ is private within this context
49 | f->remMsg(&lhs);
| ^
In file included from Message.cc:4:
Folder.h:33:10: note: declared private here
33 | void remMsg(Message*);
| ^~~~~~
Message.cc:51:23: error: ‘void Folder::remMsg(Message*)’ is private within this context
51 | f->remMsg(&rhs);
| ^
In file included from Message.cc:4:
Folder.h:33:10: note: declared private here
33 | void remMsg(Message*);
| ^~~~~~
Message.cc:57:23: error: ‘void Folder::addMsg(Message*)’ is private within this context
57 | f->addMsg(&lhs);
| ^
In file included from Message.cc:4:
Folder.h:32:10: note: declared private here
32 | void addMsg(Message*);
| ^~~~~~
Message.cc:59:23: error: ‘void Folder::addMsg(Message*)’ is private within this context
59 | f->addMsg(&rhs);
| ^
In file included from Message.cc:4:
Folder.h:32:10: note: declared private here
32 | void addMsg(Message*);
| ^~~~~~
Why complains about private methods while Folder
and Message
classes are friends?
CodePudding user response:
Since the function void swap(Message&, Message&)
is not a friend of the class Folder
, calls to private member functions such as Folder::remMsg()
and Folder::addMsg()
are not allowed within that function.