Elg*_*rov 0 c++ friend private-members
我正在尝试重写教科书(C++ Primer)中显示的程序。这是一个类似电子邮件的小程序,包含两个 mainMessage和Folder类。源文件如下:
文件夹.h
\n#pragma once\n\n#include <set>\n#include <string>\n\n#include "Message.h"\n\nusing std::string;\nusing std::set;\n\n\nclass Folder {\n friend class Message;\n friend void swap(Folder&, Folder&);\n\npublic:\n Folder(const string &fname):\n name(fname) { }\n Folder(const Folder&);\n Folder& operator=(const Folder&);\n ~Folder();\n\n void print_debug();\n\nprivate:\n string name;\n set<Message*> msgs;\n\n void add_to_Message(const Folder&);\n void remove_from_Message();\n\n void addMsg(Message*);\n void remMsg(Message*);\n};\nRun Code Online (Sandbox Code Playgroud)\n消息.h
\n#pragma once\n\n#include <string>\n#include <set>\n\nusing std::set;\nusing std::string;\n\nclass Folder;\n\nclass Message {\n friend class Folder;\n friend void swap(Message&, Message&);\n\npublic:\n // folders is implicitly initialized to the empty set\n explicit Message(const string &str = ""):\n contents(str) { }\n // copy control to manage pointers to this Message\n Message(const Message&);\n Message& operator=(const Message&);\n ~Message();\n // add/remove this Message from the specified Folder's set of messages\n void save(Folder&);\n void remove(Folder&);\n\n void print_debug();\nprivate:\n\n string contents;\n set<Folder*> folders;\n\n void add_to_Folders(const Message&);\n void remove_from_Folders();\n\n void addFldr(Folder*);\n void remFldr(Folder*);\n\n};\nRun Code Online (Sandbox Code Playgroud)\n文件夹.cc
\n#include <iostream>\n\n#include "Message.h"\n#include "Folder.h"\n\nvoid swap(Folder &lhs, Folder &rhs) {\n using std::swap;\n\n lhs.remove_from_Message();\n rhs.remove_from_Message();\n\n swap(lhs.msgs, rhs.msgs);\n swap(lhs.name, rhs.name);\n\n lhs.add_to_Message(lhs);\n rhs.add_to_Message(rhs);\n}\n\nFolder::Folder(const Folder &f):\n msgs(f.msgs)\n{\n add_to_Message(f);\n}\n\nFolder::~Folder() {\n remove_from_Message();\n}\n\nFolder& Folder::operator=(const Folder &rhs) {\n remove_from_Message();\n msgs = rhs.msgs;\n name = rhs.name;\n add_to_Message(rhs);\n\n return *this;\n}\n\nvoid Folder::addMsg(Message *msg) {\n msgs.insert(msg);\n}\n\nvoid Folder::remMsg(Message *msg) {\n msgs.erase(msg);\n}\n\nvoid Folder::add_to_Message(const Folder &f) {\n for (auto m : msgs)\n m->addFldr(this);\n}\n\nvoid Folder::remove_from_Message() {\n for (auto m : msgs)\n m->remFldr(this);\n}\n\nvoid Folder::print_debug() {\n std::cout << "Folder name : " << name << std::endl;\n std::cout << "Messages : ";\n for (const auto msg : msgs)\n std::cout << msg->contents << " ";\n std::cout << std::endl;\n}\nRun Code Online (Sandbox Code Playgroud)\n留言抄送
\n#include <iostream>\n\n#include "Message.h"\n#include "Folder.h"\n\nMessage::Message(const Message &msg):\n contents(msg.contents), folders(msg.folders)\n{\n add_to_Folders(msg);\n}\n\nMessage& Message::operator=(const Message &rhs) {\n remove_from_Folders();\n contents = rhs.contents;\n folders = rhs.folders;\n add_to_Folders(rhs);\n\n return *this;\n}\n\nMessage::~Message() {\n remove_from_Folders();\n}\n\nvoid Message::save(Folder &f) {\n folders.insert(&f);\n f.addMsg(this);\n}\n\nvoid Message::remove(Folder &f) {\n folders.erase(&f);\n f.remMsg(this);\n}\n\nvoid Message::add_to_Folders(const Message &msg) {\n for (auto f : msg.folders)\n f->addMsg(this);\n}\n\nvoid Message::remove_from_Folders() {\n for (auto f: folders)\n f->remMsg(this);\n}\n\nvoid swap(Message &lhs, Message &rhs) {\n using std::swap;\n\n for (auto f: lhs.folders)\n f->remMsg(&lhs);\n for (auto f : rhs.folders)\n f->remMsg(&rhs);\n\n swap(lhs.folders, rhs.folders);\n swap(lhs.contents, rhs.contents);\n\n for (auto f : lhs.folders)\n f->addMsg(&lhs);\n for (auto f : rhs.folders)\n f->addMsg(&rhs);\n}\n\nvoid Message::addFldr(Folder *f) {\n folders.insert(f);\n}\n\nvoid Message::remFldr(Folder *f) {\n folders.erase(f);\n}\n\nvoid Message::print_debug() {\n std::cout << "Message content : " << contents << std::endl;\n std::cout << "Exists in folders : ";\n for (const auto f : folders)\n std::cout << f->name << " ";\n std::cout << std::endl;\n}\nRun Code Online (Sandbox Code Playgroud)\n主程序.cc
\n#include "Message.h"\n#include "Folder.h"\n\nint main() {\n Folder f1("folder1");\n Folder f2("folder2");\n Message msg1("msg 1");\n Message msg2("msg 2");\n Message msg3("msg 3");\n\n msg1.save(f1);\n msg2.save(f1);\n msg2.save(f2);\n msg3.save(f2);\n\n f1.print_debug();\n f2.print_debug();\n msg1.print_debug();\n msg2.print_debug();\n msg3.print_debug();\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n当我尝试使用命令编译这些源文件时:
\ng++ main.cc Message.cc Folder.cc\nRun Code Online (Sandbox Code Playgroud)\n它给出错误:
\nMessage.cc: In function \xe2\x80\x98void swap(Message&, Message&)\xe2\x80\x99:\nMessage.cc:49:23: error: \xe2\x80\x98void Folder::remMsg(Message*)\xe2\x80\x99 is private within this context\n 49 | f->remMsg(&lhs);\n | ^\nIn file included from Message.cc:4:\nFolder.h:33:10: note: declared private here\n 33 | void remMsg(Message*);\n | ^~~~~~\nMessage.cc:51:23: error: \xe2\x80\x98void Folder::remMsg(Message*)\xe2\x80\x99 is private within this context\n 51 | f->remMsg(&rhs);\n | ^\nIn file included from Message.cc:4:\nFolder.h:33:10: note: declared private here\n 33 | void remMsg(Message*);\n | ^~~~~~\nMessage.cc:57:23: error: \xe2\x80\x98void Folder::addMsg(Message*)\xe2\x80\x99 is private within this context\n 57 | f->addMsg(&lhs);\n | ^\nIn file included from Message.cc:4:\nFolder.h:32:10: note: declared private here\n 32 | void addMsg(Message*);\n | ^~~~~~\nMessage.cc:59:23: error: \xe2\x80\x98void Folder::addMsg(Message*)\xe2\x80\x99 is private within this context\n 59 | f->addMsg(&rhs);\n | ^\nIn file included from Message.cc:4:\nFolder.h:32:10: note: declared private here\n 32 | void addMsg(Message*);\n | ^~~~~~\nRun Code Online (Sandbox Code Playgroud)\n为什么要抱怨私有方法,而Folder类Message却是朋友?
由于该函数void swap(Message&, Message&)不是类的友元,因此在该函数内不允许Folder调用私有成员函数,例如Folder::remMsg()和。Folder::addMsg()