使用友字提高效率

C++ - Use friend keywords to improve efficiency?

本文关键字:提高效率      更新时间:2023-10-16

例如,我有这两个类(来自c++ Primer的练习):

class Message{
   set<Folder> folders;
public:
   void addFolder(Folder f);
}
class Folder{
   set<Message> messages;
public:
   void addMessage(Message m);
}

方法addFolder(等于addMessage)是这样的:

void addFolder(Folder f){
    folders.push_back(f);
    f.addMessage(this);
}
void addMessage(Message m){
    messages.push_back(m);
    m.addFolder(this);
}

问题是,这样我将对这两个方法进行无限递归调用(文件夹添加消息,然后消息添加文件夹并要求文件夹添加消息等)。

我有两个解决方案:

1。在每个类中都有一个返回bool值的public成员,该值指示给定的消息/文件夹是否在对象的集合中:

void addFolder(Folder f){
    folders.push_back(f);
    if(!f.search(this)){
       f.addMessage(this);
    }
}
void addMessage(Message m){
    messages.push_back(m);
    if(!m.search(this)){
        m.addFolder(this);
    }
}

这应该可以工作,但每次我都要控制两次设置。

另一个解决方案是在每个类中都有一个私有成员,它只添加文件夹/消息,而不要求其他类添加它。那就把这个送给班上的朋友。

class Message{
   friend class Folder;
   set<Folder> folders;
public:
   void  addFolder(Folder f);
private:
   void insertFolder(Folder f){ folders.push_back(f);}
}
class Folder{
   friend class Message;
   set<Message> messages;
public:
   void addMessage(Message m);
private:
   void insertMessage(Message m){ messages.push_back(m);}
}

addMessage和addFolder方法将是:

void addFolder(Folder f){
    folders.push_back(f);
    f.insertMessage(this);
}
void addMessage(Message m){
    messages.push_back(m);
    m.insertFolder(this);
}

这样就不会有递归调用,而且性能会更好。

在这种情况下,使用friend来提高效率是可以的。或者最好使用性能较差的方式(比如搜索方式?),不要使用朋友关键字?

你的设计有很多问题。您正在递归,因为消息有文件夹,文件夹有消息。你需要比较文件夹和消息,你没有所有权的概念。

你需要暂时忘记代码,看看数据建模。

您有一组文件夹。我假设每个文件夹都有一个文件夹id。您有一组消息。每个都有一个消息id。

文件夹和消息之间有多对多关系。

给定消息id,您应该能够看到包含该消息的所有文件夹。给定一个文件夹id,您应该能够看到它包含的所有消息。

我假设"文件夹有消息",但实际上它只是一个多对多关系。可以使用两个multimaps来存储关系。

std::multimap< FolderId, MessageId >;
std::multimap< MessageId, FolderId >;

您还需要正则映射

std::map< FolderId, Folder >;
std::map< MessageId, Message >;

在最后两个映射中的FolderMessage中,您可以使用智能指针类型来实现放置和检索。我会简单地使用shared_ptr

除了multimaps,您还可以在每个Folder/Message对象中包含一个集合。这只是一个Id到Id的映射。然后,您将引用"管理器",即主映射来检索底层对象。

所以我们可以有

class Message
{
   std::set< FolderId > folderIds; // folders I am in
  // implement construction and access functions etc.
};
typedef std::shared_ptr< Message > MessagePtr;
class Folder
{
   std::set< MessageId > messageIds; // messages in this folder
};
typedef std::shared_ptr< Folder > FolderPtr;

把大地图放进某种管理器

class MessageFolderManager
{
    std::map< FolderId, FolderPtr > folders
    std::map< MessageId, MessagePtr > messages;
};

注意,对于依赖项,Folder和Message可能只需要知道其他类型的id,而不需要知道其他类型本身。因此,在Folder.h中,您将只包含MessageId的标头定义,反之亦然。这样就不会出现依赖问题。管理器需要包含所有的类类型