13.4

来源:互联网 发布:java中如果不用static 编辑:程序博客网 时间:2024/06/04 18:37

13.33
因为我们需要改变Folder本身,所以必须是Folder&

13.34
@pezy

#include <string>#include <set>class Folder;class Message {    friend void swap(Message &, Message &);    friend class Folder;public:    explicit Message(const std::string &str = ""):contents(str) { }    Message(const Message&);    Message& operator=(const Message&);    ~Message();    void save(Folder&);    void remove(Folder&);    void print_debug();private:    std::string contents;    std::set<Folder*> folders;    void add_to_Folders(const Message&);    void remove_from_Folders();    void addFldr(Folder *f) { folders.insert(f); }    void remFldr(Folder *f) { folders.erase(f); }};void swap(Message&, Message&);class Folder {    friend void swap(Folder &, Folder &);    friend class Message;public:    Folder() = default;    Folder(const Folder &);    Folder& operator=(const Folder &);    ~Folder();    void print_debug();private:    std::set<Message*> msgs;    void add_to_Message(const Folder&);    void remove_from_Message();    void addMsg(Message *m) { msgs.insert(m); }    void remMsg(Message *m) { msgs.erase(m); }};void swap(Folder &, Folder &);
#include <iostream>void swap(Message &lhs, Message &rhs) {    using std::swap;    lhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    rhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    swap(lhs.folders, rhs.folders);    swap(lhs.contents, rhs.contents);    lhs.add_to_Folders(lhs); // Use existing member function to avoid duplicate code.    rhs.add_to_Folders(rhs); // Use existing member function to avoid duplicate code.}// Message Implementationvoid Message::save(Folder &f) {    addFldr(&f); // Use existing member function to avoid duplicate code.    f.addMsg(this);}void Message::remove(Folder &f) {    remFldr(&f); // Use existing member function to avoid duplicate code.    f.remMsg(this);}void Message::add_to_Folders(const Message &m) {    for (auto f : m.folders)        f->addMsg(this);}Message::Message(const Message &m)     : contents(m.contents), folders(m.folders) {    add_to_Folders(m);}void Message::remove_from_Folders() {    for (auto f : folders)        f->remMsg(this);    // The book added one line here: folders.clear(); but I think it is redundant and more importantly, it will cause a bug:    // - In Message::operator=, in the case of self-assignment, it first calls remove_from_Folders() and its folders.clear()     //   clears the data member of lhs(rhs), and there is no way we can assign it back to lhs.    //   Refer to: http://stackoverflow.com/questions/29308115/protection-again-self-assignment    // - Why is it redundant? As its analogous function Message::add_to_Folders(), Message::remove_from_Folders() should ONLY    //   take care of the bookkeeping in Folders but not touch the Message's own data members - makes it much clearer and easier    //   to use. As you can see in the 2 places where we call Message::remove_from_Folders(): in Message::operator=, folders.clear()    //   introduces a bug as illustrated above; in the destructor ~Message(), the member "folders" will be destroyed anyways, why do    //   we need to clear it first?}Message::~Message() {     remove_from_Folders(); }Message &Message::operator=(const Message &rhs) {    remove_from_Folders();    contents = rhs.contents;    folders = rhs.folders;    add_to_Folders(rhs);    return *this;}void Message::print_debug() {     std::cout << contents << std::endl; }// Folder Implementationvoid swap(Folder &lhs, Folder &rhs) {    using std::swap;    lhs.remove_from_Message();    rhs.remove_from_Message();    swap(lhs.msgs, rhs.msgs);    lhs.add_to_Message(lhs);    rhs.add_to_Message(rhs);}void Folder::add_to_Message(const Folder &f) {    for (auto m : f.msgs)        m->addFldr(this);}Folder::Folder(const Folder &f)     : msgs(f.msgs) {     add_to_Message(f); }void Folder::remove_from_Message() {    for (auto m : msgs)        m->remFldr(this);}Folder::~Folder() {     remove_from_Message(); }Folder &Folder::operator=(const Folder &rhs) {    remove_from_Message();    msgs = rhs.msgs;    add_to_Message(rhs);    return *this;}void Folder::print_debug() {    for (auto m : msgs)        std::cout << m->contents << " ";    std::cout << std::endl;}int main() {     return 0;}

13.35
新的Message可能不会正确的匹配带到Folder中

13.36
@pezy

#include <string>#include <set>class Folder;class Message {    friend void swap(Message &, Message &);    friend class Folder;public:    explicit Message(const std::string &str = ""):contents(str) { }    Message(const Message&);    Message& operator=(const Message&);    ~Message();    void save(Folder&);    void remove(Folder&);    void print_debug();private:    std::string contents;    std::set<Folder*> folders;    void add_to_Folders(const Message&);    void remove_from_Folders();    void addFldr(Folder *f) { folders.insert(f); }    void remFldr(Folder *f) { folders.erase(f); }};void swap(Message&, Message&);class Folder {    friend void swap(Folder &, Folder &);    friend class Message;public:    Folder() = default;    Folder(const Folder &);    Folder& operator=(const Folder &);    ~Folder();    void print_debug();private:    std::set<Message*> msgs;    void add_to_Message(const Folder&);    void remove_from_Message();    void addMsg(Message *m) { msgs.insert(m); }    void remMsg(Message *m) { msgs.erase(m); }};void swap(Folder &, Folder &);
#include <iostream>void swap(Message &lhs, Message &rhs) {    using std::swap;    lhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    rhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    swap(lhs.folders, rhs.folders);    swap(lhs.contents, rhs.contents);    lhs.add_to_Folders(lhs); // Use existing member function to avoid duplicate code.    rhs.add_to_Folders(rhs); // Use existing member function to avoid duplicate code.}// Message Implementationvoid Message::save(Folder &f) {    addFldr(&f); // Use existing member function to avoid duplicate code.    f.addMsg(this);}void Message::remove(Folder &f) {    remFldr(&f); // Use existing member function to avoid duplicate code.    f.remMsg(this);}void Message::add_to_Folders(const Message &m) {    for (auto f : m.folders)        f->addMsg(this);}Message::Message(const Message &m)     : contents(m.contents), folders(m.folders) {    add_to_Folders(m);}void Message::remove_from_Folders() {    for (auto f : folders)        f->remMsg(this);    // The book added one line here: folders.clear(); but I think it is redundant and more importantly, it will cause a bug:    // - In Message::operator=, in the case of self-assignment, it first calls remove_from_Folders() and its folders.clear()     //   clears the data member of lhs(rhs), and there is no way we can assign it back to lhs.    //   Refer to: http://stackoverflow.com/questions/29308115/protection-again-self-assignment    // - Why is it redundant? As its analogous function Message::add_to_Folders(), Message::remove_from_Folders() should ONLY    //   take care of the bookkeeping in Folders but not touch the Message's own data members - makes it much clearer and easier    //   to use. As you can see in the 2 places where we call Message::remove_from_Folders(): in Message::operator=, folders.clear()    //   introduces a bug as illustrated above; in the destructor ~Message(), the member "folders" will be destroyed anyways, why do    //   we need to clear it first?}Message::~Message() {     remove_from_Folders(); }Message &Message::operator=(const Message &rhs) {    remove_from_Folders();    contents = rhs.contents;    folders = rhs.folders;    add_to_Folders(rhs);    return *this;}void Message::print_debug() {     std::cout << contents << std::endl; }// Folder Implementationvoid swap(Folder &lhs, Folder &rhs) {    using std::swap;    lhs.remove_from_Message();    rhs.remove_from_Message();    swap(lhs.msgs, rhs.msgs);    lhs.add_to_Message(lhs);    rhs.add_to_Message(rhs);}void Folder::add_to_Message(const Folder &f) {    for (auto m : f.msgs)        m->addFldr(this);}Folder::Folder(const Folder &f)     : msgs(f.msgs) {     add_to_Message(f); }void Folder::remove_from_Message() {    for (auto m : msgs)        m->remFldr(this);}Folder::~Folder() {     remove_from_Message(); }Folder &Folder::operator=(const Folder &rhs) {    remove_from_Message();    msgs = rhs.msgs;    add_to_Message(rhs);    return *this;}void Folder::print_debug() {    for (auto m : msgs)        std::cout << m->contents << " ";    std::cout << std::endl;}int main() {     return 0;}

13.37
@pezy

#include <string>#include <set>class Folder;class Message {    friend void swap(Message &, Message &);    friend class Folder;public:    explicit Message(const std::string &str = ""):contents(str) { }    Message(const Message&);    Message& operator=(const Message&);    ~Message();    void save(Folder&);    void remove(Folder&);    void print_debug();private:    std::string contents;    std::set<Folder*> folders;    void add_to_Folders(const Message&);    void remove_from_Folders();    void addFldr(Folder *f) { folders.insert(f); }    void remFldr(Folder *f) { folders.erase(f); }};void swap(Message&, Message&);class Folder {    friend void swap(Folder &, Folder &);    friend class Message;public:    Folder() = default;    Folder(const Folder &);    Folder& operator=(const Folder &);    ~Folder();    void print_debug();private:    std::set<Message*> msgs;    void add_to_Message(const Folder&);    void remove_from_Message();    void addMsg(Message *m) { msgs.insert(m); }    void remMsg(Message *m) { msgs.erase(m); }};void swap(Folder &, Folder &);
#include <iostream>void swap(Message &lhs, Message &rhs) {    using std::swap;    lhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    rhs.remove_from_Folders(); // Use existing member function to avoid duplicate code.    swap(lhs.folders, rhs.folders);    swap(lhs.contents, rhs.contents);    lhs.add_to_Folders(lhs); // Use existing member function to avoid duplicate code.    rhs.add_to_Folders(rhs); // Use existing member function to avoid duplicate code.}// Message Implementationvoid Message::save(Folder &f) {    addFldr(&f); // Use existing member function to avoid duplicate code.    f.addMsg(this);}void Message::remove(Folder &f) {    remFldr(&f); // Use existing member function to avoid duplicate code.    f.remMsg(this);}void Message::add_to_Folders(const Message &m) {    for (auto f : m.folders)        f->addMsg(this);}Message::Message(const Message &m)     : contents(m.contents), folders(m.folders) {    add_to_Folders(m);}void Message::remove_from_Folders() {    for (auto f : folders)        f->remMsg(this);    // The book added one line here: folders.clear(); but I think it is redundant and more importantly, it will cause a bug:    // - In Message::operator=, in the case of self-assignment, it first calls remove_from_Folders() and its folders.clear()     //   clears the data member of lhs(rhs), and there is no way we can assign it back to lhs.    //   Refer to: http://stackoverflow.com/questions/29308115/protection-again-self-assignment    // - Why is it redundant? As its analogous function Message::add_to_Folders(), Message::remove_from_Folders() should ONLY    //   take care of the bookkeeping in Folders but not touch the Message's own data members - makes it much clearer and easier    //   to use. As you can see in the 2 places where we call Message::remove_from_Folders(): in Message::operator=, folders.clear()    //   introduces a bug as illustrated above; in the destructor ~Message(), the member "folders" will be destroyed anyways, why do    //   we need to clear it first?}Message::~Message() {     remove_from_Folders(); }Message &Message::operator=(const Message &rhs) {    remove_from_Folders();    contents = rhs.contents;    folders = rhs.folders;    add_to_Folders(rhs);    return *this;}void Message::print_debug() {     std::cout << contents << std::endl; }// Folder Implementationvoid swap(Folder &lhs, Folder &rhs) {    using std::swap;    lhs.remove_from_Message();    rhs.remove_from_Message();    swap(lhs.msgs, rhs.msgs);    lhs.add_to_Message(lhs);    rhs.add_to_Message(rhs);}void Folder::add_to_Message(const Folder &f) {    for (auto m : f.msgs)        m->addFldr(this);}Folder::Folder(const Folder &f)     : msgs(f.msgs) {     add_to_Message(f); }void Folder::remove_from_Message() {    for (auto m : msgs)        m->remFldr(this);}Folder::~Folder() {     remove_from_Message(); }Folder &Folder::operator=(const Folder &rhs) {    remove_from_Message();    msgs = rhs.msgs;    add_to_Message(rhs);    return *this;}void Folder::print_debug() {    for (auto m : msgs)        std::cout << m->contents << " ";    std::cout << std::endl;}int main() {     return 0;}

13.38
@Mooophy The copy and swap is an elegant way when working with dynamicly allocated memory. In the Message class , nothing is allocated dynamically. Thus using this idiom makes no sense and will make it more complicated to implement due to the pointers that point back.

0 0
原创粉丝点击