C++ Copy Control 정리 (복사 생성자 확장) #2
2021. 12. 9. 23:47ㆍc++/기초
Copy Control Example
a mail-hanling application
Message와 Folder 클래스로 구성.
각 Message는 다수의 Folder들에 생길 수 있다.
주어진 Message의 contents는 하나의 카피만이 존재한다. 즉 하나의 주소를 가진다는 이야긴 것 같다.
원래 메세지가 바뀌면 각 폴더에 저장된 메세지의 내용이 모두 바뀐다.
메세지에 저장된 폴더의 주소를 저장한 포인터 리스트가 있다.
동시에 각각 폴더는 해당 메세지의 주소를 갖고 있다.

Message는 save와 remove 명령을 제공한다. (특정 폴더로부터 메세지를 추가하거나 제거한다.)
복사: 메세지를 복사할 경우 복사된 message와 원래 메세지를 구분해서 저장한다.
그러나 복사된 두 메세지는 Folder class의 set에 같이 위치한다.
삭제 : 메세지가 삭제되면 이 메세지를 갖고 있는 폴더에서도 삭제가 되어야 한다.
메세지를 다른 메세지에 할당할 때:
오른쪽에 있는 객체의 내용을 왼쪽 객체에 replace해야 한다.
왼쪽 객체에 대해서
반드시 폴더들의 set에도 업데이트가 되어야 한다.
이전에 오른쪽 객체를 저장했던 폴더를 왼쪽 객체를 가르키게끔 한다.
종합적으로 소멸자와 =연산자는 메세지를 저장한 Folder들로부터 이 메세지를 가르키는 포인터를 제거해야 한다.
copy 생성자와 =연산자는 메세지를 저장한 폴더를 새로 메세지에 추가해야 한다.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class Message;
class Folder {
friend void swap(Folder&, Folder&);
public :
Folder(const Folder&);
Folder& operator= (const Folder&);
~Folder();
void addMsg(Message* m);
void remMsg(Message* m);
private:
std::set<Message*> messages;
void add_to_message(const Folder&);
void remove_from_message();
};
void Folder::remMsg(Message* m)
{
messages.insert(m);
}
void Folder::addMsg(Message* m) {
messages.insert(m);
}
void Folder::add_to_message(const Folder& f) {
for (auto* m : f.messages) {
m->folders.insert(this);
}
}
void Folder::remove_from_message() {
for (auto* m: messages) {
m->folders.erase(this);
}
}
Folder::Folder(const Folder& f) {
add_to_message(f);
messages = f.messages;
}
Folder::~Folder() {
remove_from_message();
}
Folder& Folder::operator=(const Folder& f) {
if (this != &f) {
remove_from_message();
add_to_message(f);
messages = f.messages;
}
return *this;
}
class Message {
friend class Folder;
friend void swap(Message& lhs, Message& rhs);
public:
explicit Message( const std:: string &str= "") :
contents(str) {}
Message(const Message&);
Message& operator= ( const Message& );
~Message();
void save(Folder&);
void remove(Folder&);
private:
string contents;
set<Folder*> folders;
void add_to_Folders(const Message&);
void 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& 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);
folders.clear();
}
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 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);
}반응형
'c++ > 기초' 카테고리의 다른 글
| C++ 템플릿 활용 예제 (컨테이너 클래스 Bag) (0) | 2022.04.12 |
|---|---|
| 13. C++ Library 2편 : Container Library가 궁금해 (0) | 2021.12.06 |
| 10. 복사 생성자 (copy constructor) 문제 풀어보기 #2 (0) | 2021.12.02 |
| 10. 복사 생성자 (copy constructor) 문제 풀어보기 #1 (0) | 2021.12.02 |
| 13. C++ Library 1편 : IO Classes가 궁금해 (0) | 2021.12.01 |