문과 코린이의, [C. C++] 기록/C++ 이론

[문과 코린이의 IT 기록장] C,C++ - 연산자 오버로딩 1 : ( operator 함수 사용법, operator+ 함수, 연산자를 오버로딩 하는데 있어서의 주의사항, 연산자 오버로딩이라고 이름이 붙은 이유는?, operator * ..

벼리네 2021. 2. 20. 14:50
반응형

[문과 코린이의 IT 기록장] C,C++ - 연산자 오버로딩 1 : 

( operator 함수 사용법, operator+ 함수, 연산자를 오버로딩 하는데 있어서의 주의사항, 연산자 오버로딩이라고 이름이 붙은 이유는?,  operator * 함수 )



- C언어에서는 불가능하지만, C++에서는 사용자 정의 연산자를 사용할 수 있다.
- ::(범위 지정), .(맴버 지정), .*(맴버 포인터로 맴버 지정)을 제외모든 연산자들은 사용할 수 있다.

ex )
1. 산술 연산자 (+, -, *)
2. 축약형 연산자 (+=, -=)
3. 비교 연산자 (>=, ==)
4. 논리 연산자 (&&, ||)
5. 맴버 선택 연산자 (->, * : 역참조 연산자 ex. 포인터 *p와 같은 것)
6. 증감 연산자 (++, --)
7. 함수 호출 연산자 ( () )
8. 배열 연산자 ( [] )


이러한 기본 연산자들을, 직접 사용자가 설계한 클래스에 맞게 정의하는 것을, 연산자 오버로딩이라고 부른다.
, 기존에 존재하던 연산자의 기본 기능에, 내가 원하는 다른 기능들을 추가하는 것이다.

 



 1. operator 함수 사용법
(반환형) operator(연산자) (연산자가 받는 인자)


 2. operator+ 함수
1) operator+함수, 오버로딩 된 연산자의 해석

 

 

#include<iostream>

using namespace std;

 

class Point { // Point 클래스

private:

int xpos, ypos;

public:

Point(int x=0,int y=0):xpos(x),ypos(y){ } // 생성자 (x=0, y=0 초기화)

void ShowPosition() const { // xpos, ypos 출력 함수 (const 맴버함수로 맴버변수 변경 불가능)

  cout << '[' << xpos << ", " << ypos << ']' << endl;

 }

Point operator+(const Point& ref) { // operator+라는이름의함수

  Point pos(xpos + ref.xpos, ypos + ref.ypos); // 새로운 객체 생성

  return pos; // pos라는 객체를 복사해서 임시객체 형태로 반환한다.

 }

};

 

int main() {

Point pos1(3, 4);

Point pos2(10, 20);

Point pos3 = pos1.operator+(pos2);
// pos1 + pos2 = pos1.operator+(pos2)
// pos1객체의, 맴버함수 operator+를 호출하면서 인자로 pos2 객체를 전달하고 있다. 이것이 반환되어, pos3을 초기화하게 된다. (이 과정에서 복사생성자가 호출된다.)

 

pos1.ShowPosition();

pos2.ShowPosition();

pos3.ShowPosition();

 

return 0;

}

 


[ 오버로딩 된 연산자의 해석 ]
- 원래는 객체와 객체를 더하는 것이 불가능하다. 그러나, operator+ 내부에 사용자가 임의로 저장해놓았기 때문에 이 예제에서는 가능하다.

 


 
2) 연산자를 오버로딩 하는 두 가지 방법

[ 연산자를 오버로딩하는 방법 ]
pos1 + pos2;
 a. 맴버함수로 오버로딩 된 경우 : pos1.operator+(pos2)
 b. 전역함수로 오버로딩 된 경우 : operator+(pos1, pos2)
  - 맴버함수로 오버로딩 되는 것이 우선호출된다.
  - 객체지향에서는 전역(global)이라는 개념이 존재하지 않는다. 따라서 보통 맴버함수로 구현하는 것이 좋다.

 

ex )

 

#include <iostream>

using namespace std;

 

class Point {

private:

int xpos, ypos;

public:

Point(int x = 0, int y = 0) :xpos(x), ypos(y) { } // 생성자

void ShowPosition() const { // xpos, ypos 출력 (const 맴버함수로 맴버변수 변경 불가능)

  cout << '[' << xpos << ", " << ypos << ']' << endl;

 }

friend Point operator+(const Point& pos1, const Point& pos2); // 전역함수
// 인자가 2개가 있다. 즉, 2개의 피연산자(피연산자 + 피연산자)를 알아야 하므로, 전역함수로 오버로딩되어야 한다는 점을 파악할 수 있다.
 cf ) 맴버함수로 오버로딩되게 하고자 한다면, 피연산자 1개(객체 + 피연산자)로 이루어져야 한다.

};

Point operator+(const Point& pos1, const Point& pos2) { // 전역함수

// Point operator+함수는, Point 클래스의 맴버에 접근할 수 있다.(Point클래스 내부에 friend선언이 되어있기 때문에)

  Point pos(pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos);

  return pos;

}

 

 

int main() {

Point pos1(3, 4);

Point pos2(10, 20);

Point pos3 = pos1 + pos2;
// +연산자가 전역함수의 형태로 오버로딩 되었으므로, operator+(pos1,pos2)로 해석이 된다.

 

pos1.ShowPosition();

pos2.ShowPosition();

pos3.ShowPosition();

return 0;

}

 

 

 


 

 

 3. 연산자를 오버로딩 하는데 있어서의 주의사항
1) 본래의 의도를 벗어난 형태의 연산자 오버로딩은 좋지 않다. ex) 값을 증가시키는, 변화시키는 목적 X
2) 연산자의 우선순위와 결합성은 바뀌지 않는다. ex) 사칙연산 준수
3) 매개변수의 디폴트 값 설정이 불가능하다.
4) 연산자의 순수 기능까지 빼앗을 수 없다. ex) operator+함수 내부에서 *연산 실행하는 경우 문제 발생



 4. 연산자 오버로딩이라고 이름이 붙은 이유는?
- 함수가 오버로딩 되면 전달되는 인자에 따라 호출되는 함수가 달라진다.
- 이와 유사하게, 연산자가 오버로딩 되면, 피연산자의 종류에 따라 연산의 방식이 달라진다. 따라서 연산자 오버로딩이라고 불리는 것이다.

 

 


 5. operator * 함수 

 

ex ) 자료형이 다른 두 피연산자를 대상으로 하는 연산

 

 

#include <iostream>

using namespace std;

 

class Point {

private:

int xpos, ypos;

public:

Point(int x = 0, int y = 0) :xpos(x), ypos(y) { } // 생성자

void ShowPosition() const { // xpos, ypos 출력 (const 맴버함수로 맴버변수 변경 불가능)

  cout << '[' << xpos << ", " << ypos << ']' << endl;

 }

Point operator*(int times) { //  operator*함수. 

  Point pos(xpos * times, ypos * times); // xpos와 ypos에, 입력한 times를 곱해준다.

  return pos; // pos 객체를 복사해서, 임시객체로 반환한다.

 }

friend Point operator*(int times, Point& ref); 

 // 교환법칙의 성립을 위한 구현을 위해서 (전역함수의 형태로 곱셈 연산자를 오버로딩 해야한다.)

};

 

Point operator*(int times, Point& ref) {

  return ref * times

}

 

int main() {

Point pos(1, 2);

Point cpy;

 

cpy = 3 * pos; // 3*pos는, Point operator*(int times, Point& ref) 이 실행됨

 cf ) 3.operator*(pos)로는 해석이 불가능하다.

cpy.ShowPosition();

 

cpy = 2 * pos * 3; 

cpy.ShowPosition();

return 0;

 

}


* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)
반응형