연산자 오버로딩 총정리
- 프로그래밍/C++
- 2011. 3. 31. 12:32
*오버로딩이 뭔지?
=>함수나 연산자를 중복정의해서 사용하는 것.
*컴파일러가 오버로딩판별하는법?
인자의 개수와, 인자의 종류, const 유무 에 따라서 오버로딩 판별함!
*연산자 오버로딩이란?
operator키워드 와 연산자를 겹쳐서 함수이름처럼!!! 쓴다.(함수와는 차이가 있다! )
*함수와 연산자오버로딩함수의 차이점?
=>
연산자오버로딩하면 함수처럼 호출 가능하다. (함수와 동일)
연산자만으로도 가능하다는 또 다른 문법을 제공한다. ( C++ 문법이다!!)
ex) x + 10 는 x.operator+(10) 이렇게 해석된다!!!!
*연산자 오버로딩 제한!
연산자오버로딩은 삼항 연산자는 안된다! ( 이항 연산, 단항 연산 가능 )
밑에 안되는 연산자를 조사해보았다. 밑에서 다시 얘기함.
밑에 안되는 연산자를 조사해보았다. 밑에서 다시 얘기함.
*연산자 오버로딩 종류
클래스 멤버함수 연산자 오버로딩과 전역함수 연산자오버로딩으로 나뉜다!
p1 + p2 ---------> 멤버 함수에 의한 오버로딩 : p1.operator+(p2)
---------> 전역 함수에 의한 오버로딩 : operator+(p1, p2)
*연산자 오버로딩 예제)))
*여기서 잠깐 질문
질문1) 같은 연산자가 멤버함수와 전역함수로 같이 정의 되어있을땐, 어떤것을 호출할까??!?!?
=> 컴파일상에서 알 수 없으니 컴파일에러!!
질문2) 그럼 전역함수가 좋으냐? 멤버함수가 좋으냐?
=> 가급적 멤버함수로 선언하는것이 좋다! (객체지향 아니겠냐~)
*연산자오버로딩 안되는 연산자
.연산자
?: 삼항연산자
.*연산자
::연산자
sizeof연산자
=>안되는 이유: C++문법자체를 파괴하는 상황을 초래할 수 있기때문
*연산자오버로딩 만들때 주의사항
1.의도가 벗어난 연산은 좋지 않다!!!!
2.디폴트 매개변수 설정이 불가능함!
(디폴트 매개변수를 설정하게 되면 함수의 호출 관계가 애매해진다!)
*단항 연산자의 오버로딩
단항 연산자 오버로딩도 가능하다( 전역함수, 멤버함수 모두 가능)
전위, 후위를 구별하기 위해서 특별한 문법을 가진다.
ex) Point& operator++(); //전위 증가
ex) Point operator++(int); //후위 증가 (여기서 int 는 정수형이라는 뜻이 아니고 문법이다!!!! )
여기서 중요한점 포인트!!!!
전위 증가는 Point& 를 리턴했고 후위는 Point를 리턴했다!!
전위연산자 Point& 로 주소를 넘겨줘야되는 이유?
=> (++전위연산자라고 가정했을때)
값을 리턴안하게 되버리면 값의 복사이기 때문에 ++한번밖에 못한다.
예를 들어 ++(++변수) 이런문장이 있고, 변수값이 1이라고 하면,
변수의 최종값은 2가 될것이다. (3을 원했는데 값의 복사로 인해 1밖에 증가가 못되는 경우가 생김)
그래서 주소값을 리턴해줘서 연속적으로 단항연산자가 계산되도록 해주는것이다!!!!
후위연산자는 왜 그냥 값을 리턴할까?
=> (++후위연산자라고 가정했을때)
후위연산자는 연산이후에 값이 증가가되야되므로, 원래 값을 temp 에 저장해놓고, 수를 증가 시킨후 temp만 리턴해주는 식을 이용!!
//ex)
{
class Point3{
int x, y;
public:
Point3(): x(0), y(0) {}
Point3(int nx, int ny) : x(nx), y(ny) {}
//단항 연산자 오버로딩
Point3& operator++()
{
x++;
y++;
return (*this);
}
Point3& operator++(int)
{
Point3 temp(x,y);
x++;
y++;
return temp;
}
};
Point3 SKPoint;
++(++SKPoint); //가능 ( 레퍼런스로 리턴 안하면 제대로된 값 안나옴 )
(SKPoint++)++; //가능 ( 값을 리턴 안하면 제대로된 값 안나옴 )
}
*교환법칙 해결하기
=> SKPoint + 3 과 3 + SKPoint 은 다르게 인식될것이다.
SKPoint + 3 은 SKPoint.operator+(3) 으로 인식되는데에 비해
3 + SKPoint 은 3.~~~~~~~~ 이게 될수가 없겠죠?!?! ㅎㅎㅎ
그러므로 교환법칙을 성립하게 하려면 전역함수를 이용해야된다!
어떻게?!?! => 전역함수 연산자 오버로딩을 해서 2개 모두 정의 해주면된다!!
*임시객체
말그대로 임시로 잠깐 객체가 생겼다가 소멸되는 객체
임시객체를 왜쓰냐?
=> 컴파일러가 임시객체에 대해선 최적화가 되서 진행된다는 사실!!
[프로그래밍/C++] - 임시객체
[프로그래밍/C++] - 임시객체
*cin,cout 연산자 오버로딩
=>cin과 cout은 각각 istream과 ostream 네임스페이스를 가진다.
cin과 cout 연산자도 중복적으로 사용되므로 연산자오버로딩이 되어있다!!
=>cin과 cout은 각각 istream과 ostream 네임스페이스를 가진다.
cin과 cout 연산자도 중복적으로 사용되므로 연산자오버로딩이 되어있다!!
주의할점은 리턴값이 istream&, ostream& 값이 어야한다.
cin과 cout을 내가 정의를 해줄땐 cin과 cout을 건드릴수 없으므로 전역변수로 선언해야한다!!!!!!
*배열의 인덱스 연산자 오버로딩
클래스(CDArray)안에 배열이 있는 경우 Array[4] 처럼 CDArray[4]를 사용하게 []연산자를 오버로딩할 수 있다.
CDArray[i] --> CDArray.operator[](i) 이런식으로 호출된다. ㅇㅋ??!?!
// ex) (CDArray 안에 int형 배열이 있다고 가정하면)
class CDArray
{
int arr[10];
public:
//배열 인덱스 연산자 오버로딩
int& operator[](int n)
{
return arr[n];
}
};
//사용부~~~~
CDArray temp;
temp[4] = 3;
중요!
여기서 int& 로 레퍼런스로 값을 리턴하는 이유는?
temp[4]를 받아왔을때 대입을 할수 있게 좌변값이 되야한다!! ㅎㅎ 그래서 레퍼런스로 리턴함
*디폴트 대입연산자
디폴트 대입연산자라는것이 있다.
얕은복사를 하는 대입을 하는 저절로 만들어주는 연산자이다!!!!
디폴트 복사생성자와 비슷한(!?)개념이지만 살짝 틀리다! (생성자와 대입의 차이)
얕은복사를 하는 대입을 하는 저절로 만들어주는 연산자이다!!!!
디폴트 복사생성자와 비슷한(!?)개념이지만 살짝 틀리다! (생성자와 대입의 차이)
대입연산자 만들땐 깊은 복사를 해주자.
*복사생성자와 대입연산자 구별하기
=>복사생성자는 초기화될때 불려지는 것이고,
대입연산자는 초기화된후 대입될때 불려지는 것이다! (Effective C++ 초반 들어가기 참고)
복사생성자와 대입연산자의 차이
복사생성자와 대입연산자의 차이
*대입연산자 구현할때 주의점
대입연산자오버로딩 주의할점(소스)
하악......
별로 안걸릴줄 알았는데 꽤 오래 걸렸음!
Effective C++ , 열혈강의, 혼연 참고해서 정리함!
연산자 오버로딩 공부하면서 느낀거... 리턴값 설정을 잘해줘야된다!!!
때와 장소에 따라 다르다!? 머 이정도?!1 ㅋㅋ
나중엔 또 다 까먹겠지만 ㅋㅋㅋ
까먹을것을 대비해서 정리해봄!
이 글을 공유하기