차근차근/C

연산자 오버로딩 총정리

예쁜꽃이피었으면 2014. 7. 29. 01:00

 *오버로딩이 뭔지? 
 =>함수나 연산자를 중복정의해서 사용하는 것.

 *컴파일러가 오버로딩판별하는법?
 인자의 개수와, 인자의 종류, 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++] - 임시객체 

 *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++ 초반 들어가기 참고)
복사생성자와 대입연산자의 차이 


*대입연산자 구현할때 주의점

 


반응형