3. 함수와 연산자 오버로딩
• 함수 오버로딩
같은 함수 이름으로 함수의 반환형이나 매개변수
를 다르게 하여 재정의하는 것
• 연산자 오버로딩
정수형, 배정도형 데이터의 덧셈 등 이미 제공된
연산을 특정 클래스의 덧셈, 곱셈 등으로 다시 정
의하여 사용하는 것
4. 연산자 오버로딩을 사용하는 이유
객체지형 언어에서는 기본 개념을 익히 후에 이미 정의된
클래스를 얼마나 적절하게 사용하는 것이 중요
클래스마다 동일하게 사용하도록 설계해서 쉽게 가져와 적
용하기 사용
기존 클래스 사용 습득에 대해 시간 단축
(e.g., strcat(str, str1); strcat(str, str2); str=str1+str2;
Class Complex {
…
Add(Complex tmp);
…
};
01 Complex c1, c2, c3;
02 c3 = c1.Add(c2)
01 c3 = c1 + c2;
5. 07 연산자 오버로딩
연산자 오버로딩의 의미
연산자 오버로딩에 대해 정리하면 다음과 같다.
연산자 오버로딩은 C++에서 기본 자료형으로 사용하는 연산자를 재정의하는 것이다.
C++에서는 연산자조차 함수로 취급하기 때문에 함수를 정의하는 방법과 동일한 방법으로 연산자를 오버
로딩할 수 있다.
연산자를 함수의 형태로 오버로딩하기 때문에 오버로딩된 연산자를 연산자 함수라고도 한다.
연산자를 정의할 때 연산에 참여하는 피연산자는 매개변수로 구현된다.
연산자를 정의할 때 매개변수의 자료형에 의해 그 연산자를 사용할 수 있는 자료형이 결정된다.
연산자 함수명은 기본 자료형에 의해 사용되던 연산자를 operator 예약어와 함께 연산 기호로 표현한다.
반환값 operator 연산자(매개변수1, 매개변수2, ...)
{
함수의 본체
}
Complex 객체를 피연산자로 하는 연산자 오버로딩
이미 수치형 자료에 사용되는 + 연산자를 Complex 객체에 대해서 연산하도록 연산자 오버로딩을 해 보자.
Complex x(10,20), y(20, 40), z;
z = x + y;
6. 07 연산자 오버로딩
두 객체를 더하려고 기술한 z = x + y; 문장은 프로그래머에게 보기 편한 형태지만 연산자 함수를 쉽게 정의
하려고 컴파일러에 의해서는 호출되는 형태로 변경해 보자.
z = x.operator+(y);
복소수의 덧셈을 구하는 멤버함수 Sum을 호출하는 구조와 동일하다.
z = x.Sum(y);
+ 연산자 함수의 정의 역시 Sum 함수와 동일하다. 단지 함수명만 Sum에서 operator로 바꾸어 놓은 것 같다.
함수로 구현한 예 연산자로 구현한 예
Complex Complex::Sum(Complex rightHand)
{
...
}
Complex 클래스에 대해서도 2가지 용도로 정의할 수 있는 - 연산자를 오버로딩해 보자. 먼저 뺄셈 용도로 사
용되는 - 연산자부터 정의해 보자.
Complex Complex::operator+(Complex rightHand)
{
...
}
Complex Complex::operator-(const Complex &rightHand) const
{
Complex res;
res.real = this->real - rightHand.real;
res.image = this->image - rightHand.image;
return res;
}
7. 피연산자가 두 개인 연산자(1)
피연산자가 두 개인 + 연산자를 오버로딩 하는 예
class Complex
{
// 중간 생략
Complex operator+(const Complex& right)
{
// 실수부와 허수부를 각각 더한다.
int real = this->real + right.real;
int imag = this->imaginary + right.imaginary;
// 결과를 보관한 복소수 객체를 반환한다.
return Complex(real, imag);
}
Complex c1(1, 1);
Complex c2(2, 2);
Complex c3(0, 0);
// + 연산자를 사용한 덧셈
c3 = c1 + c2; // c3 = (3, 3)
c3 = c1.operator +(c2);
소스-1 Complex 클래스 참고
8. 일반 함수를 사용한 연산자 오버로딩(1)
멤버 함수가 아닌 일반 함수를 사용해서 + 연산자를 오버로딩
하는 예
Complex operator+(const Complex& left, const Complex& right)
{
// 실수부와 허수부를 각각 더한다.
int real = left.real + right.real;
int imag = left.imaginary + right.imaginary;
// 결과를 보관한 복소수 객체를 반환한다.
return Complex(real, imag);
}
int main()
{
Complex c1(1, 1);
Complex c2(2, 2);
Complex c3(0, 0);
// + 연산자를 사용한 덧셈
c3 = c1 + c2; // c3 = (3, 3)
c3 = operator +(c1, c2);
return 0;
}
11. 허수의 덧셈
멤버 함수 추가
ImaginaryNumber AddImaginary(const ImaginaryNumber ima);
자 자신과 개버수를 더해서 결과 와 리턴함
멤버 함수 실와
ImaginaryNumber ImaginaryNumber::AddImaginary(const ImaginaryNumber ima)
{
ImaginaryNumber res;
res.a=this->a+ima.a;
res.b=this->b+ima.b;
return res;
}
객체 덧셈와 위한 함수 실와
17. 소스 13-9 (ch13_ImanginaryNumber.cpp)
ImaginaryNumber ImaginaryNumber::operator++(void) //연산자 오버로딩에 와
해 추가된 연산자 함수
{
this->a++;
return *this;
}
ImaginaryNumber ImaginaryNumber::operator++(int dummy)
{
this->b++;
return *this;
}
소스-3 증감 연산자 오버로딩 참고
18. 실습 – 시간 클래스 정의하기
클 클래스스:래 Time
멤 수버스버: 시, 분, 초 시 를간위초와로초실스스스수 와는부를스스위간스는스를스
멤 수함스버:
생 자성1: 버수를멤버스 래스개버수스0으 로 초스로
생 자성2: 시, 분, 초 초 로를개버하버전수수 스로와멤스스버스스와
초 함버 수 전멤시멤산 를 버간버하위간와스와스는로는스스스스스스CalSecond( )
각 함수버 멤전실버멤 하스버와는스스스스
각 함멤수있버버는스멤전객 수스버 부를스스와로할스스스스
'00시 00분 00초' 는 함수멤버 스를하객는부스에스하로스
19. 소스 13-10 (ch13_Time.h)
#ifndef _TIME_
#define _TIME_
#include <iostream>
#include <string>
#define HOUR_SEC 3600
#define MIN_SEC 60
using namespace std;
class Time
{
public :
Time();
Time(const int hour, const int min, const int sec);
void SetHour(const int hour);
void SetMin(const int min);
void SetSec(const int sec);
int GetHour();
int GetMin();
int GetSec();
int CalSec();
string ShowTime();
private :
int hour, min, sec;
int t_sec;
};
#else
#endif
20. Time 클래스에 <=, >= 오버로딩하기
멤버 함수 선언
bool operator<=(Time timeObj);
bool operator>=(Time timeObj);
멤버 함수 실와
bool Time::operator<=(Time timeObj)
{
this->CalSec();
timeObj.CalSec();
if (this->t_sec<=timeObj.t_sec)
return true;
else
return false;
}
21. 소스 13-16 (ch13_06.cpp) Time 클래스 테스트
#include "ch13_Time.h"
int main()
{
Time t1(7,30,20);
cout << t1.ShowTime() << endl;
cout << "시간 - 초 위 : " << t1.CalSec() << endl;
Time t2(4,50,23);
if (t1>=t2)
cout << t1.ShowTime() << "래 " << t2.ShowTime() << "보다 크거 같다!!" << endl;
else
cout << t2.ShowTime() << "래 " << t1.ShowTime() << "보다 크거 같다!!" << endl;
if (t1<=t2)
cout << t2.ShowTime() << "래 " << t1.ShowTime() << "보다 크거 같다!!" << endl;
else
cout << t1.ShowTime() << "래 " << t2.ShowTime() << "보다 크거 같다!!" << endl;
return 0;
}
22. 07 연산자 오버로딩
연산자를 오버로딩할 때의 주의사항
C++에서 이미 사용하던 연산자만 오버로딩할 수 있다. $ 기호는 C++에서 연산자로 사용되지 않는다. 그러
므로 operator$( ) 함수를 정의할 수 없다.
이항 연산자는 이항 연산자로, 단항 연산자는 단항 연산자로만 오버로딩할 수 있다. 예를 들면 10%4와 같이
% 연산자는 이항 연산자 형태로 오버로딩해야 한다. 다음은 잘못된 예다.
int a;
% a; // 나머지를 구하는 연산자를 단항 연산자로 사용하지 못한다.
Complex x;
% x; // 나머지를 구하는 연산자를 단항 연산자로 오버로딩할 수 없다.
C++에서 사용하는 연산자 중에서 다음 연산자는 오버로딩할 수 없다. .(멤버 참조 연산자), ::(스코프 연산자),
?:(조건 연산자 ), sizeof(sizeof 연산자 ), *(포인터 연산자)
연산자를 오버로딩하려면 피연산자가 적어도 하나 이상은 사용자 정의 자료형이어야 한다. 이는 기본 자료형
에 대한 연산자 오버로딩을 방지하기 위해서다. 다음은 잘못된 예다.
double operator+(double x, double y) // 잘못된 연산자 오버로딩
대부분의 연산자는 멤버함수 또는 프렌드 함수로 오버로딩할 수 있다. 그러나 다음 연산자는 멤버함수로만
오버로딩할 수 있다.
=(대입 연산자 ), ( )(함수 호출 연산자), [ ](첨자 지정 연산자), ->(객체 포인터에 대한 멤버 참조 연산자)