Message.h
#pragma once
#include <iostream>
#include <set>
#include <string>
#include "Folder.h"
class Folder;
class Message {
friend class Folder;
friend void swap(Message &lhs, Message &rhs);
public:
explicit Message(const std::string &s)
: m_content(s) {}
Message(const Message &m);
Message &operator=(const Message &m);
Message(Message &&); // 不声明为noexcept是因为会执行insert,有可能会有bad_alloc异常
Message &operaor=(Message &&);
~Message();
void save(Folder&);
void remove(Folder&);
void addFld(Folder *);
void remFld(Folder *);
private:
std::set<Folder *> m_folders;
std::string m_content;
void add_to_folders(Message &);
void remove_from_folders();
void move_folders(Message *);
public:
void debug_print();
};
Message.cpp
#include "Message.h"
Message::Message(const Message &m)
: m_folders(m.m_folders), m_content(m.m_content) {
add_to_folders(*this);
}
Message &Message::operator=(const Message &m) {
remove_from_folders();
m_folders = m.m_folders;
m_content = m.m_content;
add_to_folders(*this);
return *this;
}
Message::Message(Message &&obj) : m_content(std::move(obj.m_content) {
move_folders(&obj);
}
Message &operaor=(Message &&m) {
if (this != &m) {
remove_from_folders();
move_folders(&m);
m_content = std::move(m.m_content);
}
return *this;
}
Message::~Message() {
remove_from_folders();
}
void Message::save(Folder &f) {
m_folders.insert(&f);
f.addMsg(this);
}
void Message::remove(Folder &f) {
m_folders.erase(&f);
f.remMsg(this);
}
void Message::add_to_folders(Message &m) {
for (auto &i:m_folders) {
i->addMsg(&m);
}
}
void Message::remove_from_folders() {
for (auto &i:m_folders) {
i->remMsg(this);
}
}
void Message::move_folders(Message *m) {
m_folders = std::move(m->m_folders);
for (auto &f:m_folders) {
f->remMsg(m);
f->addMsg(this);
}
m->clear();
}
void swap(Message &lhs, Message &rhs) {
for (auto m:lhs.m_folders) {
m->remMsg(&lhs);
}
for (auto m:rhs.m_folders) {
m->remMsg(&rhs);
}
using std::swap;
swap(lhs.m_content, rhs.m_content);
swap(lhs.m_folders, rhs.m_folders);
for (auto i:lhs.m_folders) {
i->addMsg(&lhs);
}
for (auto i:rhs.m_folders) {
i->addMsg(&rhs);
}
}
void Message::addFld(Folder *f) {
m_folders.insert(f);
}
void Message::remFld(Folder *f) {
m_folders.erase(f);
}
void Message::debug_print()
{
std::cout << "Message:\n\t" << m_content << std::endl;
std::cout << "Appears in " << m_folders.size() << " Folders" << std::endl;
}
Folder.h
#pragma once
#include <iostream>
#include <string>
#include <set>
#include "Message.h"
class Message;
class Folder {
friend class Message;
friend void swap(Folder &lhs, Folder &rhs);
public:
Folder() : m_msgs(), m_name() {}
explicit Folder(const std::string &s)
: m_msgs(), m_name(s) {}
Folder(const Folder& f);
Folder &operator=(const Folder&);
void add_to_message(Folder &);
void remove_from_message();
void addMsg(Message *);
void remMsg(Message *);
void save(Message &m);
void remove(Message &m);
private:
std::set<Message *> m_msgs;
std::string m_name;
public:
void debug_print();
};
Folder.cpp
#include <set>
#include "Folder.h"
Folder::Folder(const Folder &f)
: m_msgs(f.m_msgs), m_name(f.m_name) {}
Folder &Folder::operator=(const Folder &f) {
remove_from_message();
m_msgs = f.m_msgs;
m_name = f.m_name;
add_to_message(*this);
return *this;
}
void Folder::add_to_message(Folder &f) {
for (auto i:m_msgs) {
i->addFld(&f);
}
}
void Folder::remove_from_message() {
while (!m_msgs.empty()) {
(*m_msgs.begin())->remFld(this);
}
}
void Folder::addMsg(Message *m) {
m_msgs.insert(m);
}
void Folder::remMsg(Message *m) {
m_msgs.erase(m);
}
void Folder::save(Message &m) {
m_msgs.insert(&m);
m.addFld(this);
}
void Folder::remove(Message &m) {
m_msgs.erase(&m);
m.remFld(this);
}
void swap(Folder &lhs, Folder &rhs) {
for (auto f:lhs.m_msgs) {
f->remFld(&lhs);
}
for (auto f:rhs.m_msgs) {
f->remFld(&rhs);
}
using std::swap;
swap(lhs.m_msgs, rhs.m_msgs);
swap(lhs.m_name, rhs.m_name);
for (auto f:lhs.m_msgs) {
f->addFld(&lhs);
}
for (auto f:rhs.m_msgs) {
f->addFld(&rhs);
}
}
void Folder::debug_print()
{
std::cout << "Folder contains " << m_msgs.size() << " messages" << std::endl;
int ctr = 1;
for (std::set<Message*>::iterator m = m_msgs.begin();
m != m_msgs.end(); ++m) {
std::cout << "Message " << ctr++ << ":\n\t" << (*m)->m_content << std::endl;
}
}
main.cpp
#include <iostream>
#include <string>
#include <vector>
#include "Message.h"
#include "Folder.h"
using namespace std;
int main() {
string s1("contents1");
string s2("contents2");
string s3("contents3");
string s4("contents4");
string s5("contents5");
string s6("contents6");
// all new messages, no copies yet
Message m1(s1);
Message m2(s2);
Message m3(s3);
Message m4(s4);
Message m5(s5);
Message m6(s6);
Folder f1;
Folder f2;
m1.save(f1); m3.save(f1); m5.save(f1);
m1.save(f2);
m2.save(f2); m4.save(f2); m6.save(f2);
m1.debug_print();
f2.debug_print();
// create some copies
Message c1(m1);
Message c2(m2), c4(m4), c6(m6);
m1.debug_print();
f2.debug_print();
// now some assignments
m2 = m3;
m4 = m5;
m6 = m3;
m1 = m5;
m1.debug_print();
f2.debug_print();
// finally, self-assignment
m2 = m2;
m1 = m1;
m1.debug_print();
f2.debug_print();
vector<Message> vm;
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m1);
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m2);
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m3);
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m4);
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m5);
cout << "capacity: " << vm.capacity() << endl;
vm.push_back(m6);
vector<Folder> vf;
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(f1);
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(f2);
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(Folder(f1));
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(Folder(f2));
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(Folder());
Folder f3;
f3.save(m6);
cout << "capacity: " << vf.capacity() << endl;
vf.push_back(f3);
return 0;
}
Result:
Message:
contents1
Appears in 2 Folders
Folder contains 4 messages
Message 1:
contents1
Message 2:
contents2
Message 3:
contents4
Message 4:
contents6
Message:
contents1
Appears in 2 Folders
Folder contains 8 messages
Message 1:
contents1
Message 2:
contents2
Message 3:
contents4
Message 4:
contents6
Message 5:
contents1
Message 6:
contents2
Message 7:
contents4
Message 8:
contents6
Message:
contents5
Appears in 1 Folders
Folder contains 4 messages
Message 1:
contents1
Message 2:
contents2
Message 3:
contents4
Message 4:
contents6
Message:
contents5
Appears in 1 Folders
Folder contains 4 messages
Message 1:
contents1
Message 2:
contents2
Message 3:
contents4
Message 4:
contents6
capacity: 0
capacity: 1
capacity: 2
capacity: 4
capacity: 4
capacity: 8
capacity: 0
capacity: 1
capacity: 2
capacity: 4
capacity: 4
capacity: 8
对于m2 = m3; m4 = m5; m6 = m3; m1 = m5;
这一段的结果和我期望的不一致,需要再看一下。