class Note{
public :
Note();
Note(Note &obj);
Note& operator=(Note &obj);
std::string getList(int idx) const;
void setList(int idx, std::string str);
~Note();
private :
std::string lists[5];
};
배열을 멤버 변수로 가진 Note클래스이다.
복사 생성자와 대입 연산자가 구현돼있다.
Note::Note(Note &obj){
for (int i = 0; i < 5; ++i)
ideas[i] = obj.lists[i];
}
Note& Note::operator=(Note &obj){
std::cout << "Note's Assignment Operator" << std::endl;
for (int i = 0; i < 5; ++i)
ideas[i] = obj.lists[i];
return (*this);
}
깊은 복사를 위해 배열의 주소가 아닌 원소를 대입한다.
class Bag{
public :
Bag();
Bag(Bag& obj);
Bag& operator=(Bag& obj);
Note *getNote(){
return (note);
};
private :
Note *note;
};
Note의 포인터를 맴버 변수로 갖는 Bag클래스이다.
Bag::Bag(Bag& obj){
note = new Note();
note = obj.note; ❌
std::cout << "create Bag" << std::endl;
}
Bag& Bag::operator=(Bag& obj){
note = obj.note; ❌
return (*this);
}
위처럼 복사 생성자와 대입 연산자를 구현하면 note는 얕게 복사되게 된다.
note가 그냥 Note타입이 아닌 Note 포인터 타입이기 때문이다!!
int main(){
Bag *i = new Bag();
Bag *j = new Bag(*i);
std::cout << "before : " << i->getNote()->getNoteList(0) << std::endl;
std::cout << "before : " << j->getNote()->getNoteList(0) << std::endl;
i->getNote()->setNoteList(0, "Go home");
std::cout << "after : " << i->getNote()->getNoteList(0) << std::endl;
std::cout << "after : " << j->getNote()->getNoteList(0) << std::endl;
return 0;
}
output >
before : ...
before : ...
after : Go home
after : Go home
실제로 얕은 복사가 된 것을 확인할 수 있다.
Bag클래스의 복사 생성자와 대입 연산자에서도 Note클래스와 마찬가지로 원소를 복사하여(getter, setter를 이용) 깊은 복사를 할 수도 있겠지만 이미 Note클래스에서 깊은 복사를 구현해뒀기때문에 또 하기엔 너무 너무 아깝다......!
포인터 타입의 멤버 변수(타입의 클래스 내부에서 깊은 복사가 구현돼있는 경우)를 깊은 복사하기 위해선 포인터를 이용하면 된다!!
Bag::Bag(Bag& obj){
note = new Note();
*note = *obj.note;
std::cout << "create Bag" << std::endl;
}
Bag& Bag::operator=(Bag& obj){
*note = *obj.note;
return (*this);
}
크게 달라진 점은 없지만
포인터를 이용하면 Note의 대입 연산자를 호출하여 복사를 진행하게 된다.
output >
Note's Assignment Operator
before : ...
before : ...
after : Go home
after : ...
깊은 복사가 된 것을 확인할 수 있다!