개발 Study

#33. operator 연산자 오버로딩

HYuk 2021. 5. 18. 16:37
728x90

#operator

operator를 사용하여 연산자 오버로딩을 구현 할 수 있다.

-> 함수의 오버로딩 규칙을 연산자에 적용한 것이다.

예를 들어 클래스에 멤버변수 i_a와 i_b를 만들었을 때

클래스+3;

이런식으로 선언하면

클래스에 있는 i_a에 +3을 하라는 건지 i_b에 +3을 하라는 건지 알 수 없다.

이때 operator 를 통해 해당 +연산자를 어떤식으로 어떻게 더할 것인지 정의해 줄 수 있다.

(+뿐만 아니라 ++, =+, =, -, -= 등 여러 연산을 operator로 정의해 줄 수 있다.)

 

#include "stdafx.h"
#include <iostream>
using namespace std;
class CLS
{
	int m_iA;
	int m_iB;
public:
	CLS(int _iA, int _iB) :m_iA(_iA), m_iB(_iB) {}

	CLS operator+(CLS& _cls) // 클래스의 덧셈에서 + 정의
	{
		return CLS(m_iA + _cls.m_iA, m_iB + _cls.m_iB);
	}
	void Func()
	{
		cout << "m_iA: " << m_iA << endl;
		cout << "m_iB: " << m_iB << endl;
	}
};

int main()
{
	CLS cls(10, 20);
	CLS cls2(20, 30);

	cls = cls + cls2;
	cls.Func();

	return 0;
}

operator 는 위와 같이 쓰인다.

반환타입 operator연산자(매개변수)

{

정의

}

로 사용해주면된다.

이는 -나 = 도 전부 동일하다.

위는 매개변수로 같은 타입의 객체를 받았지만

int형을 받는거 또한 가능하다.

#include "stdafx.h"
#include <iostream>
using namespace std;
class CLS
{
	int m_iA;
	int m_iB;
public:
	CLS(int _iA, int _iB) :m_iA(_iA), m_iB(_iB) {}

	CLS operator+(int _i) // 클래스의 덧셈에서 + 정의
	{
		return CLS(m_iA + _i, m_iB);
	}
	void Func()
	{
		cout << "m_iA: " << m_iA << endl;
		cout << "m_iB: " << m_iB << endl;
	}
};

int main()
{
	CLS cls(10, 20);

	cls = cls + 3;
	cls.Func();

	return 0;
}

이러면 이때 cls+3의 값은

cls의 m_iA에 +3이 되고

Func에 의한 결과값은 13, 20이 출력되게 된다.

 

이때 operator+는

어떠한 방식으로 불려와 지는 것이냐면

cls+3;은 

cls.operator+(3);

으로 사용되는것 이기 때문에

객체가 좌측에 있어야한다.

 

3+cls;로 진행 하게 될 경우 오류를 볼 수 있는데

이때 이 교환법칙을 성립시키려면 따로 구현을 해줘야한다.

교환법칙을 위해서는 연산자 오버로딩을 전역에 구현해야 한다.

-> 이때 인자중 하나는 객체타입 이거나 객체의 레퍼런스 타입이 와야한다.

 

CLS operator+(int _i)의 교환법칙을 위해

전역에

CLS operator+(int _i, CLS& _cls)

{

return _cls + _i;

}

 

이런식으로 선언해주면

3+cls;도 작동하게 된다.


#operator=

 

CLS& operator=(CLS& _cls)
{
m_iA = _cls.m_iA;
m_iB = _cls.m_iB;

return *this;
}

 

operator=의 경우 연속대입 (a=b=c)을 위해 반환타입을 해주는 것이 좋고

operator=은 함수가 종료되어도 자기 자신은 메모리에서 소멸되지 않기 때문에

연산속도를 높이기 위해서 &(레퍼런스)를 사용한다.

 

여기서 위처럼 대입연산자를 오버로딩 해주지 않아도 디폴트 대입연산자를 통해 대입연산이 가능하다.

 

객체생성 시 대입연산자복사생성자의 호출이다.

CLS cls2 = cls1;

 

객체 생성 후 사용하는 대입 연산자대입 연산자의 호출이다.

CLS cls2;

cls2 = cls1;

 

디폴트 대입 연산자는 복사 생성자 처러 얕은 복사가 이루어 질 수 있기 때문에

대입 연산자를 정의하게 되면 깊은 복사 방식으로 하는 것이 좋다.


#operator를 통한 전위증감 및 후위증감 구현

 

전위 증감은 (++i) 자기자신을 1증가 시키고 그것을 연산에 사용하는 것이다.

후위 증감은  (i++) 본체를 복사해두고 자기자신을 1증가 시키고 연산에는 복사시킨 (아직 1이 증가 안한)값을 사용하는 것이다.

 

전위증감을 구현 할 때 단항 연산 이기 때문에 매개변수는 없다.

CLS& operator++()

{

++m_iA;

++m_iB;

return *this;

}

 

후위증감은 전위증감과 구분 하기위해 매개변수에 int를 써준다 (매개변수는 받아온다는 뜻이 아님)

CLS operator++(int)

{

CLS Temp(*this); // 현재 값을 Temp에 복사해줌

++m_iA;

++m_iB;

 

return Temp; // 이때 Temp값은 사라지는 값 이므로 레퍼런스 반환을 해주지 않는다.

}

 

 


#임시객체

변수명이 없이 선언하면 코드라인에서만 잠시 메모리에 등록되었다가 사라지는것을 임시객체라고 한다.

예를들면

CLS();

이런식으로 클래스의 변수를 따로 지정하지 않고

클래스(); 로 하게되면 해당 코드라인에서 생성되었다가 코드라인이 지나가면 사라지게 된다.

이때 임시객체도 생성자의 호출에 의해 완성되기 때문에 생성자가 호출되게 된다.

 

728x90

'개발 Study' 카테고리의 다른 글

#35. 클래스 템플릿  (0) 2021.05.21
#34. Template 및 inline  (0) 2021.05.20
#32. 바인딩  (0) 2021.05.14
#31. 캐스팅(형변환)  (0) 2021.05.14
#30. 오버라이딩, virtual, 객체포인터  (0) 2021.05.13