1 c++primer 13 .4 Message-Folder类的实现
先上代码,图省事,就全写在.h里了。
还发现一个现象,函数定义如果直接写在class里,编译会报错,在下面写成inline就没问题了。
这可能涉及到一些编译时刻处理顺序的问题,我现在还在学习阶段,实在有点搞不懂这个。
//c++primer 13章练习
#pragma once
#include <string>
#include <set>
class Message;
class Folder {
public:
friend Message;
friend void swap(Message& first, Message& second);
Folder() {}
//Folder类的 拷贝、赋值运算符、swap 和Message类基本一样,就省略了
~Folder();
void addMessage(Message& m);
void removeMessage(Message& m);
bool hasMessage(const Message& m);
const std::set<Message*>& getMessages() const;
private:
std::set<Message*> messages;
};
class Message {
public:
friend Folder;
friend void swap(Message& first, Message& second);
Message(const std::string& s = "");
Message(const Message& that);
Message operator=(Message that);
~Message();
void addToFolder(Folder& f);
void removeFromFolder(Folder& f);
bool isInFolder(const Folder& f);
std::string& getContext();
private:
std::string context;
std::set<Folder*> inFolders;
};
inline Folder::~Folder() {
for (auto& m : messages) {
m->inFolders.erase(this);
}
}
inline void Folder::addMessage(Message& m) {
messages.insert(&m);
m.inFolders.insert(this);
}
inline void Folder::removeMessage(Message& m) {
messages.erase(&m);
m.inFolders.erase(this);
}
inline bool Folder::hasMessage(const Message& m)
{
return m.inFolders.find(this) != m.inFolders.end();
}
inline const std::set<Message*>& Folder::getMessages() const {
return messages;
}
inline void swap(Message& first, Message& second) {
using std::swap;
for (auto& f : first.inFolders) {
f->messages.erase(&first);
f->messages.insert(&second);
}
for (auto& f : second.inFolders) {
f->messages.erase(&second);
f->messages.insert(&first);
}
swap(first.context, second.context);
swap(first.inFolders, second.inFolders);
}
inline Message::Message(const std::string& s) {
context = s;
}
inline Message::Message(const Message& that) {
this->context = that.context;
this->inFolders = that.inFolders;
for (auto& f : that.inFolders) {
addToFolder(*f);
}
}
inline Message Message::operator=(Message that) {
swap(*this, that);
return *this;
}
inline Message::~Message() {
for (auto& f : inFolders) {
f->messages.erase(this);
}
}
inline void Message::addToFolder(Folder& f) {
f.messages.insert(this);
inFolders.insert(&f);
}
inline void Message::removeFromFolder(Folder& f) {
f.messages.erase(this);
inFolders.erase(&f);
}
inline bool Message::isInFolder(const Folder& f){
return f.messages.find(this) != f.messages.end();
}
inline std::string& Message::getContext() {
return context;
}
我在写代码过程中遇到的一些问题
我写的版本和书上的版本差别还是有点大的
书上的版本往Folder添加Message用的save方法,调用到了
f.addMsg(this),也就是说将Message存入Folder时,会同时更新Message和Folder里的set,但是使用Folder的addMsg却只会更新Folder自己的set,我个人感觉这非常不利于直观使用,但是如果将Folder::addMsg里也加上调用Message::save`的语句,那这两句就会一直循环调用所以在加入和移出信息时,我选择直接操作两边的set,不借用函数,这样就可以同时实现
m1.addToFolder(f1); f2.addMessage(m2);更符合直观的使用
不过这样我个人感觉也有不好的地方,两个类都直接操作了另一个类的private成员,感觉这和封装的理念有点冲突,虽然操作都只是一行代码
inFolders.erase(this), 但还是不够优雅。(一些可能可行的建议)或许可以在Folder和Message里再分别加上一个private方法Folder::private_addMessage ; Message::private_addToFolder这两个方法不对外开放,只供内部和友元使用void Message::private_addToFolder(Folder& f) { inFolders.insert(&f); } void Folder::private_addMessage( Message& m) { messages.insert(&m); }这两个方法只对自己和友元开放,用来封装添加进set的语句
不过总感觉这种写法还是不够优雅,不过继续下去改进可能就设计一些设计模式知识了,我个人还在学习过程中,目前能想到最好的写法就这个了,希望有大神看到了,能提点建议
版权声明:本文为lgg1111原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。