【问题标题】:C++ compiler doesn't consider friend class declarationC++ 编译器不考虑友元类声明
【发布时间】:2021-10-11 18:09:18
【问题描述】:

我正在尝试重写教科书(C++ Primer)中显示的程序。这是一个类似于电子邮件的小型程序,包含两个主要的MessageFolder 类。源文件如下:

文件夹.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*);

};

文件夹.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;
}

ma​​in.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;
}

当我尝试使用命令编译这些源文件时:

g++ main.cc Message.cc Folder.cc

报错:

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*);
      |          ^~~~~~

为什么在 FolderMessage 类是朋友时抱怨私有方法?

【问题讨论】:

  • void swap(Message&amp;, Message&amp;) 不是文件夹类的朋友。
  • 谢谢!我不知道我应该将访问私有成员的函数也声明为朋友。
  • @nielsen 您可能希望将该评论作为实际答案提交。

标签: c++ friend private-members


【解决方案1】:

由于函数 void swap(Message&amp;, Message&amp;) 不是类 Folder 的友元,因此不允许在该函数中调用私有成员函数,例如 Folder::remMsg()Folder::addMsg()

【讨论】:

    猜你喜欢
    • 2010-12-31
    • 2020-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 2017-09-12
    • 2021-06-23
    • 2014-04-07
    相关资源
    最近更新 更多