안녕하세요 삽잡이 입니다~
이번 시간에는 연산자 중복 정의에 대해서 알아보려고 합니다...
시작하죠 푸하하...
1+1 가 뭔가요? 귀요미 아니죠... 2입니다... 껄껄껄
우리는 당연하게 1+1은 2라고 합니다..
그런데 말입니다...
이 '+' 라는 기능을 C++에서는 개발자 마음대로 중복 정의를 할 수 있게 됩니다...
이름하여 연산자 중복정의 (연산자 오버로딩) 라고 합니다...
이 연산자 중복정의는,
제공하는 개발자가 사용하는 개발자에게 편의를 주기 위해서 제공하는 기능입니다.
왜냐, 어차피 이런 연산자 중복정의해봤자 일반 사람이 쓰겠습니까? ㅎㅎ
결국은 개발자가 사용할 것이니,
제공하는 개발자가 사용하는 개발자에게.... 라는 말로 설명을 드렸습니다.
1+1, 4-2, 9*3 등등...
피 연산자들이 기존에 약속되어있으면 안되고,
우리가 정의한, 즉, 최소 하나 이상이 사용자 정의 형식일 경우에만
연산자 중복정의를 할 수 있게 됩니다.
다시 정리해서 말씀드리자면,
연산자 중복정의 (오버로딩) 를 통해서 연산자는 하나지만 그 하나의 연산자로
여러 가지 기능을 제공해준다는 것입니다.
실제 코드를 보며 이게 뭐하는 기능일지 보여드리겠습니다..
백문이 불여일견... 푸하하 유식한척
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Sap { int x; int y; public: Sap(int _x=0, int _y=0) { x = _x; y = _y; } }; void main() { Sap sap1(1, 2); Sap sap2(10, 20); Sap sap3; sap3 = sap2-sap1; } | cs |
자... 이코드는 당연하게 sap2의 객체에서 sap1의 객체를 뺐으니 sap3에는 9와 18이 저장될까요?
땡입니다... 왜일까요?
컴파일러가 모르기 때문입니다...
Sap이라는 Class는 제가 만든 데이터 타입이구...
컴파일러 입장에서는 난생 처음 보는 망칙한 놈이 연산을 해달라고 하는데
알아들을 수 있겠습니까...
이와 같이 우리가 정의한 데이터 타입을 컴파일러 입장에서는 해석할 수 없기 때문에
우리가 따로 중복 정의를 해줘야한다는 것입니다...
이런것을 왜 사용할까요?
굳이 사용할 필요가 있고 없고는... 각 개발자마다 호불호가 나뉘겠죠...
이 기능을 대체할 수 있는 방법이 없는게 아니니까요
Java언어 같은 경우에는 이와 같은 기능을 제공하지 않고 있으며,
C#같은 경우에는 빈틈을 보이지 않게 엄격하게 제공하고 있습니다....
아무튼... 그래도 우리가 프로그래밍을 하면서
자체적으로 라이브러리 만들고 사용하는것만은 아니기 때문에
다른 사용자들이 만든 라이브러리에 이와 같은 기능이 포함되어있다면...
그러니 물론 알아둔다 해서 나쁠것이 없다고 생각하기에...
조금은 더 알아보도록 하겠습니다...
그래서 결론적으로 말씀드리자면,
위의 코드와 같은 경우를 대비하여 컴파일러와 약속을 했습니다.
operator라는 키워드와 연산자를 쓴 뒤에
새로 약속을 정의하는 것이죠...
1 2 3 4 5 6 7 | Sap operator-(Sap &sap1, Sap &sap2) { int x = sap2.GetX() - sap1.GetX(); int y = sap2.GetY() - sap1.GetY(); Sap sap(x, y); return sap; } | cs |
이처럼,
연산에 대해 반환할 형을 쓰고 operator와 연산자를 같이 쓴 뒤에 전달할 인자를 써주면
새롭게 연잔자를 중복 정의할 수 있게 된다는 것입니다...
위와같이 중복정의를 했다는 것은 이제 또 성가신 일이 생겼다는 것을 알 수 있게됩니다...
sap3 = sap2-10;
이와 같은 경우라면? 알아서 sap2객체의 x 변수와 y변수 에 10을 빼줄까요?
아뇨... 이것 또한 정의를 해줘야한다는 것이죠...
일일히 다 해줘야합니다 푸하하.... 그래서 C#에서는 엄격하다고 말했던 것이죠...
C#같은 경우에는 연산자 오버로딩을 할 경우
예를들어 A > B 와 같은 중복 정의를 한다 하면
A >= B, A < B, A <= B 아래의 모든 경우도 다 정의를 해주지 않으면
오류를 발생시킵니다... 그래서 엄격하다고....
아무튼...
지금까지는 전역함수에 의한 연산자 중복정의(오버로딩)을 알아봤습니다....
연산자를 오버로딩 하는 방법에는 또 하나의 방법이 있습니다...
바로 멤버함수에 의해서도 위 와같은 기능이 가능한데요,
약간의 차이가 있습니다...
위의 코드에서 operator- 함수의 위치에 여부에 따라서
그러니까... 클래스 안에 있느냐 밖에 있느냐에 따라
전역함수/ 멤버함수에 의한 오버로딩으로 바뀐다는 것입니다...
멤버 함수에 의한 오버로딩을 살펴보고 둘의 차이를 알아보도록 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class Sap { int x; int y; public: Sap(int _x=0, int _y=0) { x = _x; y = _y; } int GetX() { return x; } int GetY() { return y; } Sap operator-(Sap &sap) { int x = this->x - sap.GetX(); int y = this->y - sap.GetY(); Sap sap(x, y); return sap; } }; void main() { Sap sap1(1, 2); Sap sap2(10, 20); Sap sap3; sap3 = sap2-sap1; } | cs |
클래스 안에서 연산자를 중복정의 했군요....
이때 컴파일러와 약속을 했습니다
"우리 좌항에 있는 객체를 기준으로하고, 우항의 객체는 인자로 생각하자!"
뭔말일까요?
즉, sap2라는 객체를 기준으로 operator- 함수를 호출하고
이 함수의 인자로 sap1을 보내겠다 이 뜻입니다...
sap2 - sap1; 이라는 연산을 컴파일러는
sap2.operator-(sap1); 이라고 알아듣겠다 이겁니다...
이건 약속입니다... 왜 좌항을 기준으로 그러냐... 왜 우항은 인자야되냐...
할말이 없게됩니다 저는... 허허... 약속이니까요!
그런데 이렇게 멤버함수에 의해 연산자 중복 정의를 할 때
문제가 생깁니다...
1 2 3 4 5 | Sap sap1(1, 2); Sap sap2(10, 20); Sap sap3; sap3 = 10 - sap1; | cs |
난 이렇게 연산을 해보겠어! 라고 한다면... 문제가 생깁니다...
x - y; 는 컴파일러에서 x.operator-(y) 라고 해석한다고 했는데요,
10.operator-(sap1); 이 가능하냐 이겁니다....
이와같이 좌항에 우리가 정의한 형식이 오지 않으니... 이런 한계가 있을 때는
위에서 설명한 전역함수에 의한 연산자 중복정의를 시행해야한다는 것입니다...
지금까지 배운 것은 이항 연산자에 관해서 연산자 중복정의를 한 것이었습니다...
이제 다른 연산자들의 중복정의를 알아봐야 할 터인데요...
다음시간에 알아보도록 하죠....
다시 한번 말씀드리지만,
연산자 중복정의는 개발자마다 호불호가 나뉩니다....
하지만 C++로 개발을 하다보면, 남들이 만든 라이브러리를 사용해야할 경우가 많은데
이런 기능이 있는 것을 체험하실 수 있으니
이것저것 많이 알아둬서 나쁠것이 없다는 점...
아무튼... 다음시간에 뵙죠...
이상 삽잡이였습니다...
'삽질의 현장 > - C++' 카테고리의 다른 글
#013_시(c)시(c)해서 C++?!_ 대입 연산자 중복 정의 (0) | 2015.07.12 |
---|---|
#012_시(c)시(c)해서 C++?!_ 배열의 인덱스 연산자 중복정의 (0) | 2015.07.12 |
#010_시(c)시(c)해서 C++?!_ 잡다구리한 것들... (싱글톤, 기능성, 다형성) (0) | 2015.07.10 |
#009_시(c)시(c)해서 C++?!_프로토 타이핑 ... (0) | 2015.07.09 |
#008_시(c)시(c)해서 C++?!_이름은 같은데 하는짓은 다 달라... 다형성 (0) | 2015.07.08 |