22. 04. 04 - 연산자 오버 로딩 : 더하기, 전치형-후치형, 일반 함수, 배열 첨자, 대입
연산자 오버 로딩
- java에서는 없다.
- 연산기호를 사용하게 해 놓으면 직관적인 면에서 유용하다
- 연산자 오버 로딩으로 ' + ' 를 해놓고 기능은 뺄셈 기능으로 해놓을 수도 있긴 하지만
- 연산기호에 맞는 기능 구현해놓는 것이 기본이다.
- 우리가 쓰던 cout << endl;에서 ((( << ))) 도 연산자 오버 로딩이었다!
연산자 오버 로딩 : operator +
복소수
- a, b가 실수이고 a + bi 꼴의 수
- 10과 10 i 출력
내가 만든 클래스에 = 내가 만든 데이터 타입에
연산 기호를 사용할 수 있나요?
No!
But!
C++에서 제공하는 ' 연산자 오버 로딩 ' 기능으로 가능하다!
operator + ( )
- 91번 하고 92번 하고 똑같은 것이다.
- 우리가 만든 Complex 객체 a로 Complex 객체 b 더하기 가능
- a클래스에서 함수 호출하는 것이랑 똑같은 것
연산자 오버 로딩 : operator ++ ( 전치형 / 후치형 )
후치형
일단 값을 대입해준 다음에- 값 증가
순서 1. 일단 이전의 값을 temp에 기록해준다.
순서 2. 값을 증가시킨다.
순서 3. 원래의 값 temp를 대입해준다.
전치형
값 증가한 다음에 대입
순서 1. 값을 증가시킨다.
순서 2. 대입시킨다.
몰라도 코드 작성하는 것은 지장 X.
다른 사람이 사용한 거 이해하는데 좋음
물론 내가 사용할 수도 있고
연산자 오버 로딩 - 일반 함수
보통 멤버 함수로 만들지만 일반 함수로 만들어야 하는 경우가 있다.
바로 - ((( 연산 기호의 왼쪽에 위치해야 하는 경우 )))
연산 기호의 왼쪽에 위치해야 하는 경우란?
연산자 오버 로딩(일반 함수로 버전) - 기본 세팅
Complex complex = 10;
cout << complex << endl;
cout << complex
- 이게 되려면 cout은 Complex객체를 받는 연산자 함수 --- << ---필요하다 .
- complex는 내가 만든 Complex 데이터 타입으로 만들어진 객체로 컴파일러는 미리 알 수 없다
- 연산자가 만들어져 있을 리가 없다.
complex . cout ( )operator<<
- 그리고 cout을 Complex 클래스 안에 만들면 ( 멤버 함수로 만들면 )
- cout이 연산자 왼쪽에 올 수 없다.
- complex << --- 식으로 사용해야 된다. - 객체로 멤버 함수 호출하는 식
- << Complex ---- 식으로 사용할 수 없다. - 함수로 객체를 호출하는 식
이처럼 멤버 함수로 구현할 수 없을 때 - 연산자의 왼쪽에 와야 하는 경우
일반 함수로 연산자 오버 로딩
## Check Point
- 클래스 외부의 일반 함수로 클래스 내부의 멤버 함수를 호출하려면
- Set( ) / Get ( ) 함수를 호출해서 접근해야 한다.
- 이번에는 friend 키워드를 추가해서 - 친구 함수를 만들어주고
- 이를 이용하여 접근하고, 연산자 오버 로딩 실습
일반 함수니까 set / get 함수를 호출해서 접근했었다. - ref . Real( ) 과 ref . Imaginary( )
함수에 friend 키워드 추가해주면 – 친구 함수가 되고 - 친구의 private영역 접근 가능하다..
friend – 클래스에도, 함수에도 사용 가능!
이처럼 일반 함수 ostream으로 연산자 << 재정의
왼쪽 연산자 << ---- 오른쪽에 - Complex 객체를 받을 수 있게 재정의한 것이다.
이제 cout << complex ; 사용 가능
자바에는 연산자 오버 로딩 없다.
연산자 오버 로딩 : [ ] 배열 첨자
기본 세팅
- 배열에 값 초기화 / 출력하는 부분
SetIndex와 GetIndex로 사용하니까 직관적이지 않다.
이럴 경우 연산자 오버 로딩을 이용하여 배열 첨자 ((( [ ] ))) 연산자 오버 로딩을 통해 직관적으로 바꿔보자.
22번 line에 - int& operator에서 & 주소 값으로 안 해주면 오류 난다. 이유는?
- index로 2가 들어왔다고 가정
- 참조 타입이 아닌 값으로 해주면
- int ~~~ _arr [2]되어서 2칸 떨어진 곳의 값을 리턴하게 되는 것이다.
- 공간이 아닌 값을 리턴 - 함수는 무엇을 리턴해줘야 하는지 항상 잘 생각해야 한다.
- [ ] 연산자는 - 공간을 리턴해줘서 - 나중에 이 공간에 값을 대입하게 해 줄 것이다.
47번 풀어보면 아래와 같은 것
array[i] = i;
array . operator[ ] ( i ) = i;
함수가 리턴한 값( LeftValue )에
i값 ( Right Value )을 대입한 것이다.
함수가 리턴함 값이 참조 공간!!
함수가 리턴한 값이 참조 값이 아니라 값이었으면
오른쪽 value 대입 불가능
연산자 오버 로딩 : = 대입 연산자
- 좌측과 우측의 데이터 타입이 동일하면 대입을 해준다.
- 주소 값을 가진 경우 문제 발생
- 오버로딩 필요
## 대입 연산자를 연산자 오버 로딩해서 사용할 경우 주의 사항
- 좌측과 우측의 데이터 타입이 동일하면 대입을 해준다.
- 주소 값을 가진 객체를 대입하는 상황 대비
- 대입이 여러 번 일어나는 경우 대비
1. 주소 값을 가진 배열 대입 대비
array = array2; 상황 - ( array2 -> array로 대입 상황 )
좌측 우측 데이터 타입이 동일하므로 실행된다.
언젠가는 문제 발생.
array에 --- 10 / 2000번지가 저장
array2의 -- 20 / 3000번지가 저장되어있었는데
array2에 저장되어있는 ---- 20 / 3000번지 그대로
array에게 대입되어서 array가 가지고 있던 원래의 데이터 미아됨 - 어디 있는지 모름
대입이 끝난 후
이제 array와 array2가 같은 주소를 사용하고 있기 때문에
복사 생성자 경우와 똑같이 에러 난다 -
이를 방지하기 위해
복사 생성자 경우와 같은 형식으로 재정의가 필요하다.
수행 로직은 복사 생성자와 동일
- array의 size 가져오고
- size만큼 공간 새로 만들어주고 ,
- 새로운 공간에 array의 값 대입
22번 Line - 위에서 했던 - 배열 첨자 [ ] 연산자 오버 로딩과
30번 Line - 지금 하는 - 대입 = 연산자 오버 로딩의
return 데이터 타입과 return 값 다른 것 check !
다른 이유 :
대입 연산자를 이어서 사용할 경우를 대비
참조 값으로 리턴을 받고 그 값으로 / 다음 대입 연산을 실행하기 위해서
2. 대입 연산자를 이어서 사용할 경우를 대비해서
return 데이터 타입 DynamicArray& 로 해주고
return 값 *this 로 해주어야 한다..
review
operator
연산자 오버 로딩이라는 새로운 기능을 배웠다.
내가 사용하고자 하는 연산 기호에
내가 원하는 기능으로 오버 로딩을 통하여
사용할 수 있게 해 줬다.
연산기호를 사용하지 않았을 경우보다
가독성도 좋아졌고, 직관적으로 보여서
코드를 이해하는 데에도 더 효율적이었다.
다만 대입 연산자처럼
연산자 오버 로딩의 하는 경우
주의할 점 체크해서 사용해야 할 것 같다.
연산자 + 와 ++ 실습할 때는
왜 굳이 이렇게 해야 되나 생각하다가
>> 기호를 사용할 때
왜 사용하는지 깨달음을.ㅎㅎ
연산자 오버 로딩 - 잘 사용하면 코드 길이도 줄고
코드도 깔끔해져서 가독성도 upup 될 것 같다.
##check point
연산자 오버 로딩 - 일반 함수로 사용해야 하는 경우
friend 함수 / 대입 연산자 오버 로딩 부분