22
13. 연연연 연연연연

13장 연산자 오버로딩

  • Upload
    -

  • View
    1.154

  • Download
    0

Embed Size (px)

Citation preview

Page 1: 13장 연산자 오버로딩

13. 연산자 오버로딩

Page 2: 13장 연산자 오버로딩

차례• 객체 연산• 연산자 오버로딩

2/14

Page 3: 13장 연산자 오버로딩

함수와 연산자 오버로딩• 함수 오버로딩같은 함수 이름으로 함수의 반환형이나 매개변수를 다르게 하여 재정의하는 것• 연산자 오버로딩정수형 , 배정도형 데이터의 덧셈 등 이미 제공된 연산을 특정 클래스의 덧셈 , 곱셈 등으로 다시 정의하여 사용하는 것

Page 4: 13장 연산자 오버로딩

(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;

기존 클래스 사용 습득에 대해 시간 단축

Page 5: 13장 연산자 오버로딩

07 연산자 오버로딩

연산자 오버로딩의 의미 연산자 오버로딩에 대해 정리하면 다음과 같다 .

연산자 오버로딩은 C++ 에서 기본 자료형으로 사용하는 연산자를 재정의하는 것이다 .

C++ 에서는 연산자조차 함수로 취급하기 때문에 함수를 정의하는 방법과 동일한 방법으로 연산자를 오버로딩할 수 있다 .

연산자를 함수의 형태로 오버로딩하기 때문에 오버로딩된 연산자를 연산자 함수라고도 한다 .

연산자를 정의할 때 연산에 참여하는 피연산자는 매개변수로 구현된다 .

연산자를 정의할 때 매개변수의 자료형에 의해 그 연산자를 사용할 수 있는 자료형이 결정된다 .

연산자 함수명은 기본 자료형에 의해 사용되던 연산자를 operator 예약어와 함께 연산 기호로 표현한다 .

Complex 객체를 피연산자로 하는 연산자 오버로딩 이미 수치형 자료에 사용되는 + 연산자를 Complex 객체에 대해서 연산하도록 연산자 오버로딩을 해 보자 .

반환값 operator 연산자 ( 매개변수 1, 매개변수 2, ...){함수의 본체}

Complex x(10,20), y(20, 40), z;z = x + y;

Page 6: 13장 연산자 오버로딩

07 연산자 오버로딩

두 객체를 더하려고 기술한 z = x + y; 문장은 프로그래머에게 보기 편한 형태지만 연산자 함수를 쉽게 정의

하려고 컴파일러에 의해서는 호출되는 형태로 변경해 보자 .

복소수의 덧셈을 구하는 멤버함수 Sum 을 호출하는 구조와 동일하다 .

+ 연산자 함수의 정의 역시 Sum 함수와 동일하다 . 단지 함수명만 Sum 에서 operator 로 바꾸어 놓은 것 같다 .

Complex 클래스에 대해서도 2 가지 용도로 정의할 수 있는 - 연산자를 오버로딩해 보자 . 먼저 뺄셈 용도로 사

용되는 - 연산자부터 정의해 보자 .

z = x.operator+(y);

z = x.Sum(y);

함수로 구현한 예 연산자로 구현한 예

Complex Complex::Sum(Complex rightHand){...}

Complex Complex::operator+(Complex right-Hand){...}

Complex Complex::operator-(const Complex &rightHand) const{ Complex res; res.real = this->real - rightHand.real; res.image = this->image - rightHand.image; return res;}

Page 7: 13장 연산자 오버로딩

피연산자가 두 개인 연산자 (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 클래스 참고

Page 8: 13장 연산자 오버로딩

일반 함수를 사용한 연산자 오버로딩 (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;}

Page 9: 13장 연산자 오버로딩

객체 연산• 허수 클래스를 정의하고 , 객체를 생성하여 허수

덧셈을 실행하기클래스 이름 : ImaginaryNumber

멤버 변수 : 실수부와 허수부의 실수 ( 허수부의 실수는 0 이 아닌 실수 )

멤버 함수 : 생성자 1: 실수부가 0, 허수부가 1 로 초기화생성자 2: 실수부와 허수부를 매개변수로 전달하여 값을 지정실수부 값과 허수부 값을 각각 전달받는 함수실수부 값과 허수부 값을 객체 외부로 전달하는 각각의 함수허수 형태로 문자열을 작성하는 함수

9/14

Page 10: 13장 연산자 오버로딩

소스 13-1 (ch13_ImaginaryNumber.h)#ifndef _IMAGINARY_#define _IMAGINARY_

#include <iostream>#include <string>using namespace std;

class ImaginaryNumber{public:

ImaginaryNumber();ImaginaryNumber(const double a, const double b);void SetA(const double a);void SetB(const double b);double GetA();double GetB();string GetImaginaryNumber();

private:double a; // 실수부double b; // 허수부 (b≠0)

};

#else#endif

Page 11: 13장 연산자 오버로딩

허수의 덧셈멤버 함수 추가

ImaginaryNumber AddImaginary(const ImaginaryNumber ima); 자기자신과 매개변수를 더해서 결과값을 리턴함

멤버 함수 정의ImaginaryNumber ImaginaryNumber::AddImaginary(const ImaginaryNum-ber ima){

ImaginaryNumber res;

res.a=this->a+ima.a;res.b=this->b+ima.b;

return res;}

객체 덧셈을 위한 함수 정의

Page 12: 13장 연산자 오버로딩

허수 덧셈 테스트소스 13-5 (ch13_02.cpp)

#include "ch13_ImaginaryNumber.h"

int main(){

ImaginaryNumber ima1(4.2,5.1);ImaginaryNumber ima2;ImaginaryNumber ima3;

ima2.SetA(7.2);ima2.SetB(9.6);

ima3=ima1.AddImaginary(ima2); //ima1 과 ima2 의 덧셈 결과가 리턴 , ima3 에 할당

cout << "( " << ima1.GetImaginaryNumber() << " ) + ";cout << "( " << ima2.GetImaginaryNumber() << " ) = ";

cout << ima3.GetImaginaryNumber() << endl;

return 0;}

Page 13: 13장 연산자 오버로딩

연산자 오버로딩 1• 연산자 오버로딩– 연산 대상에 대한 연산자 재정의

3+4 정수의 덧셈 연산 가능함 !!!class TEST{ ….};TEST a, b;a+b 연산 불가능 , TEST 의 객체를 대상으로 하는 덧셈 연산 오버로딩해야함

string str1(“computer”), str2(“science”);str1+str2 연산 가능 , string 객체를 대상으로 하는 덧셈 연산이 오버로딩되어 있음

13/14

Page 14: 13장 연산자 오버로딩

연산자 오버로딩 2• 연산자 오버로딩 함수 프로토타입

함수반환형 operator 연산자 ( 연산대상 );

ImaginaryNumber 클래스에 덧셈 연산 함수를 정의하면 ~

함수 선언 :ImaginaryNumber operator+(const ImaginaryNumber object);

함수 정의 :ImaginaryNumber ImaginaryNumber::operator+(const ImaginaryNumber object) // 연산자 오버로딩에 의해 추가된 연산자 함수{

ImaginaryNumber res;

res.a=this->a+object.a;res.b=this->b+object.b;

return res;} 14/14

Page 15: 13장 연산자 오버로딩

소스 13-6 (ch13_03.cpp)허수의 덧셈 객체 연산자 오버로딩 테스트 ~

#include "ch13_ImaginaryNumber.h"

int main(){

ImaginaryNumber ima1(2.7,6.3);ImaginaryNumber ima2;ImaginaryNumber ima3;

ima2.SetA(7.2);ima2.SetB(9.6);

ima3=ima1+ima2; // 연산자 오버로딩으로 인해 덧셈 연산자 사용 가능 !!

cout << "( " << ima1.GetImaginaryNumber() << " ) + ";cout << "( " << ima2.GetImaginaryNumber() << " ) = ";

cout << ima3.GetImaginaryNumber() << endl;

return 0;}

소스 -2 연산자 오버로딩 참고

Page 16: 13장 연산자 오버로딩

증감 연산자 오버로딩• 증감 연산자– 선 증감 : ++a, --a– 후 증감 : a++, a--

클래스형 operator++( ); // 선 증감 연산자 오버로딩클래스형 operator++(int dummy); // 후 증감 연산자 오버로딩

ImaginaryNumber 클래스의 증가 연산자 오버로딩

ImaginaryNumber operator++(void);ImaginaryNumber operator++(int dummy);

16/14

Page 17: 13장 연산자 오버로딩

소스 13-9 (ch13_ImanginaryNumber.cpp)

ImaginaryNumber ImaginaryNumber::operator++(void) // 연산자 오버로딩에 의해 추가된 연산자 함수{

this->a++;return *this;

}

ImaginaryNumber ImaginaryNumber::operator++(int dummy){

this->b++;return *this;

}

소스 -3 증감 연산자 오버로딩 참고

Page 18: 13장 연산자 오버로딩

실습 – 시간 클래스 정의하기

클래스 이름 : Time멤버 변수 : 시 , 분 , 초를 나타내는 부호 없는 정수와 초 단위로 시간을 나타냄멤버 함수 :

생성자 1: 매개변수 없이 멤버 변수를 0 으로 초기화생성자 2: 시 , 분 , 초의 멤버 변숫값을 매개변수로 전달하여 초기화초 단위로 시간을 나타내는 멤버 변숫값을 계산하는 멤버 함수 CalSecond( )각 멤버 변숫값을 설정하는 멤버 함수각 멤버 변숫값을 외부로 전달할 수 있는 멤버 함수'00 시 00 분 00 초 ' 형태로 외부에 전달하는 멤버 함수

Page 19: 13장 연산자 오버로딩

소스 13-10 (ch13_Time.h)

#ifndef _TIME_#define _TIME_

#include <iostream>#include <string>#define HOUR_SEC 3600#define MIN_SEC 60using 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

Page 20: 13장 연산자 오버로딩

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;

elsereturn false;

}

Page 21: 13장 연산자 오버로딩

소스 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;}

Page 22: 13장 연산자 오버로딩

07 연산자 오버로딩

연산자를 오버로딩할 때의 주의사항 C++ 에서 이미 사용하던 연산자만 오버로딩할 수 있다 . $ 기호는 C++ 에서 연산자로 사용되지 않는다 .

그러

므로 operator$( ) 함수를 정의할 수 없다 .

이항 연산자는 이항 연산자로 , 단항 연산자는 단항 연산자로만 오버로딩할 수 있다 . 예를 들면 10%4 와 같이

% 연산자는 이항 연산자 형태로 오버로딩해야 한다 . 다음은 잘못된 예다 .

int a;

% a; // 나머지를 구하는 연산자를 단항 연산자로 사용하지 못한다 .

Complex x;

% x; // 나머지를 구하는 연산자를 단항 연산자로 오버로딩할 수 없다 .

C++ 에서 사용하는 연산자 중에서 다음 연산자는 오버로딩할 수 없다 . .( 멤버 참조 연산자 ), ::( 스코프 연산자 ),

?:( 조건 연산자 ), sizeof(sizeof 연산자 ), *( 포인터 연산자 )

연산자를 오버로딩하려면 피연산자가 적어도 하나 이상은 사용자 정의 자료형이어야 한다 . 이는 기본 자료형

에 대한 연산자 오버로딩을 방지하기 위해서다 . 다음은 잘못된 예다 .

double operator+(double x, double y) // 잘못된 연산자 오버로딩 대부분의 연산자는 멤버함수 또는 프렌드 함수로 오버로딩할 수 있다 . 그러나 다음 연산자는 멤버함수로만

오버로딩할 수 있다 .

=( 대입 연산자 ), ( )( 함수 호출 연산자 ), [ ]( 첨자 지정 연산자 ), ->( 객체 포인터에 대한 멤버 참조 연산자 )