c++ 개발자는 기본적으로 사용자에 입장에서 코드를 작성해야 한다.
사용자가 사용하기 쉬운 코드는 추상성,직관성,편리성이 높은 코드를 의미한다
다음 코드를 보자
MyClass a;
a.Append(3, int);
MyClass a;
a += 3;
둘다 기존 a에 3을 추가하는 내용이지만 사용자 입장에서는 두 코드의 난이도는 다르다.
그렇기에 우리는 사용자가 더욱 잘 소프트웨어를 사용할수 있게 클래스의 연산자 다중 정의를 통해
여러 기능을 제공해야 한다
연산자 함수는 연산자를 호출할 수 있는 메서드 이다
기본적인 예시 코드를 살펴보자
class CMyData
{
public:
CMyData()
{
}
CMyData(int number)
:m_nData(number)
{
}
~CMyData()
{
}
operator int()
{
return m_nData;
}
int operator+(CMyData rhs)
{
this->m_nData = this->m_nData + rhs.m_nData;
return m_nData;
}
void operator=(int nParam)
{
m_nData = nParam;
}
private:
int m_nData = 0;
};
//사용자 코드
int main(void)
{
CMyData a(3);
CMyData b(4);
CMyData c;
c = a + b;
cout << c << endl;
c = 4 ;
cout << c << endl;
}
출력결과
7
4
앞서 코드에서 중요하게 봐야할 부분은 c = a+b , c=4 부분이다
두 코드는 사용자 입장에서 연산자 처럼 보이지만 정확히 함수 이다.
그렇기에 기본 연산으로 만든 함수는 절대로 실패 해서는 안된다.
그렇기에 사용자에 맞춰 예외처리 등이 필요하다.
여기서 생각을 조금 더 확장해 보자
만약 다음처럼 코드 작성되면 어떻게 될까?
a = b = 5;
당연히 오류가 발생한다
b = 5는 우리가 int 값을 매계변수 로 받는 연산자를 정의했지만 a = b 는 클래스를 매계변수로 하는 연산자를 정의하지 않았다.
그러면 위에 문제를 해결하는 방법에 대해 알아보자
첫번쨰로 int 값을 반환하도록 연산자를 정의하는것이다
void operator=(int nParam)
{
m_nData = nParam;
}
기존코드
int operator=(int nParam)
{
m_nData = nParam;
return m_nData;
}
바뀐 코드
이렇게 바꾸면 정상적으로 출력이 되는것을 확인할수 있다.
하지만 이러한 방식에도 문제점이 존재한다
b=5까지는 정상적으로 연산자를 진행하면 된다 하지만 b=5가 반환하는 값은 int다
그렇다면 a=b는 엄연히 클래스대 클래스 연산인데 int반환 연산자로 호출이 된다.
그렇기에 연산자를 하나더 정의 하자
CMyData operator=(CMyData rhs)
{
m_nData = rhs.m_nData;
return m_nData;
}
클래스 반환 연산자
이렇게 바꾸면 b=5는 int형 연산자로 a=b는 클래스형 연산자로 제대로 작동한다
하지만 여기서 임시객체 문제를 마주하게 된다
클래스 반환 연산자를 살펴 보면 기본적으로 클래스 인스턴스를 2개를 임시객체로 만든다
(매개변수로 받은 rhs 1개 , return 으로 만드는 클래스 1개)
임시객체는 성능저하에 원인으로 지금부터 임시객체 문제 해결을 위해 2가지를 바꿔보자
- 1.함수의 매개변수가 클래스인 경우 무조건 참조로 받는 것이 좋다
CMyData operator=(const CMyData& rhs)
{
m_nData = rhs.m_nData;
return m_nData;
}
함수의 매개변수 클래스를 참조형으로 받으면 불필요한 임시객체를 만들지 않아도 된다.
참고로 참조형으로 받을떄 const도 세트로 붙여주자 !!
CMyData& operator=(const CMyData& rhs)
{
m_nData = rhs.m_nData;
return *this;
}
우리가 대입을 하기위해서 operatro=에 복사본을 만든 다음에 대입을 할필요가 없다.
기본적으로 operator= 자체를 참조 반환을 통해 인스턴스를 줄일 수 있다