Post
[ STUDY/Effective C++ ]
2022. 9. 8. 16:26
복사생성자와 복사대입연산자를 통틀어 객체 복사 함수(copy function)이라고한다. 객체 복사함수는 컴파일러가 자동으로 만들어내기도하며 복사되는 객체가 갖고있는 데이터를 빠짐없이 복사하는 동작을하고있다.
하지만 컴파일러가 아닌 우리가 객체 복사함수를 만드는것이 컴파일러에게는 꽤나 기분이 나쁠 수도있다. 그래서 우리에게 복사함수 구현이 틀려도 조용히 있을경우가 있다.
class Customer{
public:
...
Customner(const Customer& rhs);
Customer& operator=(const Customer& rhs);
...
private:
std::string name;
};
Customer::Customer(const Customer& rhs)
: name(rhs.name) //rhs데이터 복사
{
logCall("customer copy constructor");
}
Customer& Customer::oprator=(const Customer& rhs)
{
loCall("Customer copy assignment operator");
name = rhs.name; //rhs데이터 복사
return *this;
}
복사함수를 직접 구현하였을 경우의 클래스이다. 문제될것이 없어보이지만 여기서 데이터 멤버 하나를 추가하면 문제가 생기기 시작한다.
private:
std::string name;
Data lastTransaction;
추가가되는 순간 이전에 있던 복사함수들은 완전 복사가 아닌 부분복사가된다. 이럴경우 우리는 클래스에 데이터 멤버를 추가하였다면 추가한 데이터 멤버를 처리하도록 복사 함수를 다시 작성해야한다.(생성자도 다시!)
그리고, 클래스를 상속한다면 조금 더 머리가 어지러워진다.
class PriorityCustomer: public Customer{
public:
...
PriorityCustomer(const PriorityCustomer& rhs);
PriorityCustomer& operator=(const PriorityCustomer& rhs);
...
private:
int priority;
};
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
: priority(rhs.priority) //rhs데이터 복사
{
logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustomer::oprator=(const PriorityCustomer& rhs)
{
loCall("PriorityCustomer copy assignment operator");
priority = rhs.priority; //rhs데이터 복사
return *this;
}
PriorityCustomer를 복사하는것같지만, 사실 Customer로부터 상속한 데이터 멤버들은 복사가 되지않고있다.
그나마 복사생성자에서는 Customer에서 상속한 name이나 lastTransaction을 초기화해주겠지만, 복사 대입연산자에서는 기본 클래스 데이터 멤버가 변경되지않고 그대로 있게된다.
PriorityCustomer::PriorityCustomer(const PriorityCustomer& rhs)
: Customer(rhs), ////////기본 클래스의 복사 생성자 호출
priority(rhs.priority)
{
logCall("PriorityCustomer copy constructor");
}
PriorityCustomer& PriorityCustomer::oprator=(const PriorityCustomer& rhs)
{
loCall("PriorityCustomer copy assignment operator");
////////////////////기본 클래스 부분 대입
Customer::operator=(rhs);
/////////////////////
priority = rhs.priority;
return *this;
}
그럴 경우에는 기본 클래스의 복사 생성자를 호출하거나, 기본 클래스 부분을 대입하면된다. 객체 복사함수는 주어진 객체의 모든 데이터 멤버 및 모든 기본 클래스 부분을 빠트리지말고 복사해야한다.
'STUDY > Effective C++' 카테고리의 다른 글
항목 14: 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자 (0) | 2022.10.28 |
---|---|
항목 13: 자원관리에는 객체가 그만! (2) | 2022.09.22 |
항목 11: operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자 (0) | 2022.08.31 |
항목 10 : 대입 연산자는 *this의 참조자를 반환하게 하자 (0) | 2022.08.24 |
항목 9 : 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자 (0) | 2022.08.17 |