5. 연산자 중복

Download Report

Transcript 5. 연산자 중복

제5장 연산자 중복
 이항 연산자 중복
 단항, (), [] 연산자 중복
 프렌드 연산자 함수
 형 변환 함수
 집합 응용 프로그램 예
 이진수 표현 응용 예
순천향대학교 정보기술공학부
이상정
1
C++ 프로그래밍
연산자 중복 (operator overloading)
 C++에서는 기존의 C 언어에서 제공하고 있는 연산자에 대
하여 그 의미를 다시 부여하는 것을 "연산자 중복" 또는 "연
산자 재정의"라 함
• 연산자 중복은 기본적으로 함수의 중복과 같이 연산자도 하나의 함수
라는 개념을 사용하여 중복 정의
• 중복되는 연산자 함수는 클래스의 멤버함수나 프렌드 함수로 정의
• 함수 이름 대신에 operator 키워드를 사용하고 다음에 연산자를 기술
반환형 operator 연산자(가인수 리스트);
순천향대학교 정보기술공학부
이상정
2
제5장 연산자 중복
C++ 프로그래밍
연산자 중복정의 예
class Complex {
………
Complex operator +(complex x);
// + 연산자 중복
………
};
Complex a, b, c;
c = a + b;
// 중복된 연산자를 사용한 복소수 덧셈 연산 표현
 복소수형 클래스 + 연산자 중복 정의 예
• operator + 는 함수와 같이 간주
• c = a + b는 c = a.operator + (b); 로 기술할 수도 있음
• 객체 a의 멤버함수 operator + 를 호출하고 인수 b를 전달
순천향대학교 정보기술공학부
이상정
3
제5장 연산자 중복
이항 연산자 중복
순천향대학교 정보기술공학부
이상정
4
C++ 프로그래밍
예제 5.1 이항 연산자 중복 예
// Ex5_1.cpp
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y) { xval = x; yval = y; }
void get_xy(int &x, int &y)
{ x = xval; y = yval; }
Point operator +(Point p); // + 연산자 중복
};
main()
{
Point pt1, pt2(3,8), pt3(11,2);
int x, y;
Point Point::operator +(Point p)
{
Point tmp;
tmp.xval = xval + p.xval;
// this->xval + p.xval
tmp.yval = yval + p.yval;
// this->yval + p.yval
return tmp;
}
pt1 : xval => 14, yval => 10
순천향대학교 정보기술공학부
이상정
pt1 = pt2 + pt3;
// 연산자 함수 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
}
재정의된 연산 pt2 + pt3는 다음과 같이
연산자 함수를 호출하여 실행한다.
pt2.operator +(pt3)
5
제5장 연산자 중복
C++ 프로그래밍
예제 5.2 복소수 연산 예 (1)
// Ex5_2.cpp
#include <iostream.h>
class Complex {
double re, im;
public:
Complex(double r, double i)
{ re = r; im = i; }
Complex()
{ re = 0; im = 0; }
Complex operator +(Complex);
// + 연산자 중복
Complex operator -(Complex);
// - 연산자 중복
void show()
{ cout << re << " + i" << im << '\n'; }
};
Complex Complex::operator +(Complex c)
{
Complex tmp;
tmp.re = re + c.re;
tmp.im = im + c.im;
return tmp;
순천향대학교
정보기술공학부
이상정
}
Complex Complex::operator -(Complex c)
{
Complex tmp;
tmp.re = re - c.re;
tmp.im = im - c.im;
return tmp;
}
main()
{
Complex a(1.2,10.6), b(2.3, 5), c(2.0,4.4);
Complex sum, dif;
sum = a + b;
// 연산자 함수 + 호출
cout << "a + b = "; sum.show();
dif = a - b;
// 연산자 함수 - 호출
cout << "a - b = "; dif.show();
sum = a + b + c; // 연산자 함수 + 호출
cout << "a + b + c = "; sum.show();
6
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.2 복소수 연산 예 (2)
a + b = 3.5 + i15.6
a - b = -1.1 + i5.6
a + b + c = 5.5 + i20
복소수 덧셈, 뺄셈을 위해 연산자 +, -를 중복 정의하였다.
각 연산자 함수가 Complex 형의 객체를 반환하므로
a + b + c 와 같이 연속적인 연산이 가능하다. 각 연산자는
다음과 같이 연산자 함수를 호출한다.
a+b
=> a.operator +(b)
a-b
=> a.operator -(b)
a + b + c => a.operator +(b).operator +(c)
순천향대학교 정보기술공학부
이상정
7
제5장 연산자 중복
C++ 프로그래밍
예제 5.3 이항 연산자 중복 예 3:
예제5.1 수정 (1)
// Ex5_3.cpp
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y)
{ xval = x; yval = y; }
void get_xy(int &x, int &y)
{ x = xval; y = yval; }
Point operator +(Point p); // + 연산자 중복 1
Point operator +(int d); // + 연산자 중복 2
};
// + 연산자 함수 1 : 객체 + 객체
Point Point::operator +(Point p)
{
Point tmp;
tmp.xval = xval + p.xval;
tmp.yval = yval + p.yval;
return tmp;
}순천향대학교 정보기술공학부
이상정
8
// + 연산자 함수 2 : 객체 + 정수
Point Point::operator +(int d)
{
Point tmp;
tmp.xval = xval + d;
tmp.yval = yval + d;
return tmp;
}
main()
{
Point pt1, pt2(3,8), pt3(11,2);
int x, y;
pt1 = pt2 + pt3; // 연산자 함수 1 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
pt1 = pt2 + 10;
// 연산자 함수 2 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
제5장 연산자 중복
}
C++ 프로그래밍
예제 5.3 이항 연산자 중복 예 3:
예제5.1 수정 (2)
pt1 : xval => 14, yval => 10
pt1 : xval => 13, yval => 18
이항 연산자의 중복 시 오른쪽의 오퍼랜드는 같은 클래스 형의
객체가 아닌 문자, 정수 등과 같은 내장 자료형(built-in type)을
정의할 수도 있다.
위의 예에서 pt2 + 10은 다음과 같은 형태로 두번째 + 연산자
함수를 호출한다.
pt2.operator +(10) 이 경우 내장 자료형은 오른쪽 오퍼랜드에만 적용
되어야 하며 10 + pt2와 같이 오른쪽에 적용 하면 에러가 발생한다.
순천향대학교 정보기술공학부
이상정
9
제5장 연산자 중복
C++ 프로그래밍
예제 5.5 관계 연산자 중복 예:
예제5.3 수정 (1)
// Ex5_5.cpp
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y)
{ xval = x; yval = y; }
void get_xy(int &x, int &y)
{ x = xval; y = yval; }
Point operator +(Point p); // + 연산자 중복 1
Point operator +(int d); // + 연산자 중복 2
int operator <(Point p) // < 연산자 중복
{ return ((xval < p.xval) && (yval < p.yval));}
};
// + 연산자 함수 1 : 객체 + 객체
Point Point::operator +(Point p)
{
Point tmp;
tmp.xval = xval + p.xval;
tmp.yval = yval + p.yval;
return tmp;
순천향대학교 정보기술공학부
이상정
}
// + 연산자 함수 2 : 객체 + 정수
Point Point::operator +(int d)
{
Point tmp;
tmp.xval = xval + d;
tmp.yval = yval + d;
return tmp;
}
main()
{
Point pt(3,8);
if (pt < pt+10) // <,+ 연산자 함수 호출
cout << "pt < pt+10\n";
else
cout << "pt >= pt+10\n";
}
10
제5장 연산자 중복
C++ 프로그래밍
예제 5.5 관계 연산자 중복 예:
예제5.3 수정 (2)
pt < pt+10
>, <, == 등과 같은 관계 연산자를 중복 정의한 예이다. 연산자 <가
클래스 내부에서 정의되었다. pt < pt+10은 다음과 같이 연산자
함수를 호출한다.
pt.operator < (pt.operator +(10))
순천향대학교 정보기술공학부
이상정
11
제5장 연산자 중복
단항, (), [] 연산자 중복
순천향대학교 정보기술공학부
이상정
12
C++ 프로그래밍
단항 연산자 중복
 ++, --, ~, ! 등과 같은 단항 연산자(unary operator)도 이항
연산자와 같이 중복 정의
 단항 연산자의 경우 하나의 오퍼랜드는 연산자 함수를 정의
하는 객체가 되므로 연산자 함수에 전달되는 인수가 없게 됨
순천향대학교 정보기술공학부
이상정
13
제5장 연산자 중복
C++ 프로그래밍
예제 5.5 단항 연산자 중복 예 1:
예제 4.13 수정
// Ex5_5.cpp
#include <iostream.h>
class Counter {
int value;
public:
Counter(int n)
Counter()
int val()
void operator ++()
cnt1 value : 11
cnt2 value : -1
{ value = n; }
{ value = 0; }
{ return value; }
{ ++value; }
// ++ 연산자 중복
void operator --()
{ --value; }
// -- 연산자 중복
};
++, --연산자는 연산자의 위치에 따라 전치
형과 후치형으로 구분되는 데 이 예에서는
모두 적용될 수 있고 같은 결과를 보인다.
++cnt1 => cnt1.operator ++()
cnt2-- => cnt2.operator --()
main()
{
Counter cnt1(10), cnt2;
++cnt1;
// 연산자 함수 ++ 호출
cnt2--;
// 연산자 함수 -- 호출
cout << "cnt1 : " << cnt1.val() << '\n';
cout << "cnt2 : " << cnt2.val() << '\n';
}순천향대학교 정보기술공학부
이상정
14
제5장 연산자 중복
C++ 프로그래밍
예제 5.6 단항 연산자 중복 예 2 (1)
// Ex5_6.cpp
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y)
{ xval = x; yval = y; }
void get_xy(int &x, int &y)
{ x = xval; y = yval; }
Point operator -(Point p);
// 이항 - 연산자 중복
Point operator -(); // 단항 - 연산자 중복
};
// 단항 - 연산자 함수
Point Point::operator -()
{
xval = -xval; yval = -yval;
return *this;
// 자기참조 : 호출한 자신의 객체 반환
}
main()
{
Point pt1(3,8), pt2(10,2);
int x,y;
pt1 = pt1 - pt2; // 이항 - 연산자 함수 호출
pt1.get_xy(x,y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
pt1 = -pt1;
// 단항 - 연산자 함수 호출
pt1.get_xy(x,y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
// 이항 - 연산자 함수
Point Point::operator -(Point p)
{
Point tmp;
tmp.xval = xval - p.xval;
tmp.yval = yval - p.yval;
return tmp;
} 순천향대학교 정보기술공학부
이상정
15
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.6 단항 연산자 중복 예 2 (2)
pt1 : xval => -7, yval => 6
pt1 : xval => 7, yval => -6
이항 - 연산자와 음수를 구하는 단항 - 연산자의 중복 예이다.
단항 연산자 함수의 정의 시 자신을 호출한 객체의 부호를 반전
시킨 뒤 바로 자신의 객체를 반환하도록 자기참조 *this 포인터의
값을 반환하였다.
pt1 - pt2 => pt1.operator -(pt2)
-pt1
=> pt1.operator -()
순천향대학교 정보기술공학부
이상정
16
제5장 연산자 중복
C++ 프로그래밍
(), [] 연산자 중복
 함수호출 연산자 ()나 첨자 연산자 []도 중복 정의
• () 연산자는 단항 또는 이항 연산자로 중복 정의
• [] 연산자는 이항 연산자로 중복 정의
순천향대학교 정보기술공학부
이상정
17
제5장 연산자 중복
C++ 프로그래밍
예제 5.7 단항 () 연산자 중복 예:
예제 5.5 수정
// Ex5_7.cpp
#include <iostream.h>
cout << "cnt1 : " << cnt1() << '\n';
// 연산자 함수 () 호출
cout << "cnt2 : " << cnt2() << '\n';
// 연산자 함수 () 호출
}
class Counter {
int value;
public:
Counter(int n)
Counter()
void operator ++()
{ value = n; }
{ value = 0; }
{ ++value; }
// ++ 연산자 중복
void operator --() { --value; }
// -- 연산자 중복
int operator ()() { return value; }
// () 연산자 중복
cnt1 value : 11
cnt2 value : -1
};
() 연산자를 전용멤버 변수 value를 반환
하는 연산자 함수로 중복 정의하였다.
main()
{
Counter cnt1(10), cnt2;
++cnt1;
// 연산자 함수 ++ 호출
cnt2--;
// 연산자 함수 -- 호출
순천향대학교 정보기술공학부
이상정
cnt1()은 다음과 같이 호출된다.
cnt1.operator ()()
18
제5장 연산자 중복
C++ 프로그래밍
예제 5.8 이항 () 연산자 중복 예:
심볼 테이블 예 (1)
// Ex5_8.cpp
#include <iostream.h>
#include <string.h>
#include <stdlib.h> // exit() 함수 정의
#define MAXNUM 100
// 최대 심볼 테이블 크기
struct Symbol {
// 심볼 테이블 형
char *name;
// 심볼 이름
int value;
// 심볼 값
};
class Symtable {
Symbol table[MAXNUM]; // 심볼 테이블
int cnt;
// 심볼 테이블 크기
public:
Symtable()
{ cnt = 0; }
void add(char *s,int v);
// 심볼 삽입
int search(char *s);
// 심볼 검색
int operator ()(char *s); // () 연산자 중복
};
순천향대학교 정보기술공학부
이상정
19
// 심볼 테이블에 (s,v) 등록
void Symtable::add(char *s, int v)
{
if (cnt < MAXNUM-1) {
table[cnt].name = new char[strlen(s)+1];
// 동적할당
strcpy(table[cnt].name,s); // 심볼 등록
table[cnt].value = v;
// 심볼 값 등록
cnt++;
// 심볼 테이블 크기 증가
}
else {
// 심볼 테이블 최대 크기 초과
cout << "! Symbol table overflow\n";
exit(1);
}
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.8 이항 () 연산자 중복 예:
심볼 테이블 예 (2)
// 심볼 이름 s로 심볼 테이블 검색하여 심볼 값 반환
int Symtable::search(char *s)
{
for (int i = 0; i < cnt; i++)
if (strcmp(s,table[i].name) == 0)
// 심볼 찾았음
return table[i].value;
return -1; // 심볼 테이블에 없으면 -1 반환
}
int Symtable::operator()(char *s)
{
cout << s << " : ";
// 심볼 이름 출력
return search(s);
}
순천향대학교 정보기술공학부
이상정
20
main()
{
Symtable sym;
sym.add("MOV",10);
sym.add("ADD",11);
sym.add("LOAD",12);
sym.add("STORE", 13);
sym.add("SHIFT", 14);
cout << sym("LOAD") << '\n';
// 연산자 함수 () 호출
cout << sym("SUB") << '\n';
// 연산자 함수 () 호출
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.8 이항 () 연산자 중복 예:
심볼 테이블 예 (3)
LOAD : 12
SUB : -1
위 프로그램은 심볼 테이블에 심볼의 이름과 심볼의 값을 등록한 후
주어진 심볼의 이름으로 심볼 테이블을 검색하여 해당 심볼의 값을
반환하는 예이다. 위 예에서 연산자 함수 ()가 심볼 테이블을 심볼의
이름으로 검색하는 함수로 중복 정의되었다.
() 연산자 함수는 이항 연산자로 사용하여 다음과 같이 심볼의 이름을
인수로 받아들였다.
sym("LOAD") => sym.operator ()("LOAD")
sym("SUB") => sym.operator ()("SUB")
순천향대학교 정보기술공학부
이상정
21
제5장 연산자 중복
C++ 프로그래밍
예제 5.9 [] 연산자 중복 예: 배열의 구현
// Ex5_9.cpp
#include <iostream.h>
#include <stdlib.h>
class Array {
int *p;
// 배열의 시작주소
int size;
// 배열의 크기
public:
Array(int num);
// 생성자
int &operator [](int i);
// [] 연산자 중복
};
main()
{
Array n(10);
Array::Array(int num)
{
p = new int[num];
if (!p) {
// 동적 메모리 할당 에러
cout << "!! Allocation error\n";
exit(1);
}
size = num;
}
순천향대학교 정보기술공학부
이상정
// [] 연산자 중복 정의
int &Array::operator [](int i)
{
if (i < 0 || i >= size) {
// 배열의 참조 범위 검사
cout << "\n!! Array bounds error\n";
exit(1);
}
return p[i];
// p[i]의 참조자 반환
}
for (int i = 0; i < 10; i++)
n[i] = i*i;
// 연산자 함수 [] 호출
// 참조자에 값 대입
for (i = 0; i < 11; i++)
cout << n[i] << ' ';
// 연산자 함수 [] 호출
22
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.8 이항 () 연산자 중복 예:
심볼 테이블 예 (3)
0 1 4 9 16 25 36 49 64 81
!! Array bounds error
[] 연산자 중복을 이용하여 객체로 배열을 구현한 예이다. 일반 배열로 선언하면
C나 C++ 언어에서는 배열 인덱스에 대한 범위 체크(boundary checking)를 하지
않는다. 따라서 배열의 참조 범위를 벗어날 수 있어 오류가 발생한다.
이 예에서는 Array 형 클래스의 []연산자 함수에서 배열을 참조 시에 먼저 배열의
인덱스(여기서는 연산자 함수의 인수)를 체크함으로써 안전하게 배열을 참조할
수 있다. 연산자 함수 []의 인수는 배열의 인덱스가 된다. 반환형은 배열의 자료
형에 대한 참조자로 선언되어야 해당 배열에 값을 대입할 수 있다.
위의 예에서는 배열 n의 크기가 10 이므로 n[0] ~ n[9] 까지의 범위를 갖는다.
따라서 두번째 for문의 실행 끝에서 i=10인 경우 n[10]이 되어 배열의 범위를 넘
서므로 좥[]좦 연산자 함수에서 에러 메세지가 출력된다.
연산자 함수는 다음과 같이 호출된다.
n[i] => n.operator [](i)
순천향대학교 정보기술공학부
이상정
23
제5장 연산자 중복
프렌드 연산자 함수
순천향대학교 정보기술공학부
이상정
24
C++ 프로그래밍
프렌드 연산자 함수
 연산자가 중복된 함수도 일반 다른 함수와 마찬가지로 클래
스의 멤버함수가 아닌 프렌드 연산자 함수로 정의하여 사용
• 프렌드 함수는 클래스의 멤버함수가 아니면서 클래스의 전용부분 자
료를 접근할 수 있는 함수
 프렌드 연산자 함수는 멤버 연산자 함수와 같이 연산자의 오
퍼랜드 중 하나를 연산자 함수를 호출하는 객체로는 표현할
수 없게 됨
• 프렌드 함수는 클래스의 멤버함수가 아니기 때문에 프렌드 함수를 호
출하는 해당 클래스형의 객체 자체를 가리키는 this 포인터를 가질 수
없음
• 단항 연산자인 경우에는 하나의 오퍼랜드가 연산자 함수의 인수로 전
달
• 이항 연산자를 재정의할 경우 두개의 오퍼랜드가 프렌드 연산자 함수
의 인수로서 전달
순천향대학교 정보기술공학부
이상정
25
제5장 연산자 중복
C++ 프로그래밍
예제 5.10: 복소수 연산 예: 예제 5.2 수정 (1)
// + 프렌드 연산자 함수
Complex operator +(Complex c1,
Complex c2)
{
Complex tmp;
// Ex5_10.cpp
#include <iostream.h>
class Complex {
double re, im;
public:
Complex(double r, double i)
{ re = r; im = i; }
Complex()
{ re = 0; im = 0; }
friend Complex operator +(Complex,
Complex);
// + 연산자 중복 : 프렌드 함수
friend Complex operator -(Complex,
Complex);
// - 연산자 중복 : 프렌드 함수
void operator ()();
// () 연산자 중복
};
tmp.re = c1.re + c2.re;
tmp.im = c1.im + c2.im;
return tmp;
}
// + 프렌드 연산자 함수
Complex operator -(Complex c1,
Complex c2)
{
Complex tmp;
tmp.re = c1.re - c2.re;
tmp.im = c1.im - c2.im;
return tmp;
순천향대학교 정보기술공학부
이상정
26
}
제5장 연산자 중복
C++ 프로그래밍
예제 5.10: 복소수 연산 예: 예제 5.2 수정 (2)
// () 연산자 함수
void Complex::operator ()()
{
cout << re << " + i" << im << '\n';
// 복소수 출력
}
sum = 5.7 + i15.6
dif = 1.1 + i5.6
여기서 +, - 는 클래스 Complex의 멤버 연
산자 함수가 아닌 외부 프렌드 연산자 함수로
정의하였다.
main()
{
Complex a(3.4,10.6), b(2.3, 5), sum, dif;
클래스 Complex의 프렌드 함수이므로
Complex의 전용멤버인 re,im을 연산자 함수
에서도 사용이 가능하다.
sum = a + b; // 프렌드 연산자 함수 + 호출
dif = a - b; // 프렌드 연산자 함수 - 호출
() 연산자 함수는 복소수를 출력하는 멤버
cout << "sum = ";
sum();
// 멤버 연산자 함수 () 호출
cout << "dif = ";
dif();
// 멤버 연산자 함수 () 호출
각 연산자 함수의 호출은 다음과 같이 기술할
연산자 함수이다.
수 있다.
a + b => operator +(a, b)
a - b => operator -(a, b)
}
sum() => sum.operator ()()
순천향대학교 정보기술공학부
이상정
27
dif()
=> dif.operator ()()제5장
연산자 중복
C++ 프로그래밍
내장 자료형 중복
 예제 5.3
• Point 형 객체의 이항 연산자 중복 시 오른쪽의 오퍼랜드가 같은 클래
스 형의 객체가 아닌 내장 자료형으로 정의하여 pt2 + 10으로 연산
하는 예
• 멤버 연산자 함수를 사용하였기 때문에 왼쪽의 연산자는 항상 이 연
산자 함수를 호출하는 클래스형으로 기술되어야 함
• 10 + pt2와 같이 기술하면 에러가 발생
 프렌드 연산자 함수를 사용하면 두개의 오퍼랜드가 연산자
함수의 인수가 되므로 멤버 연산자 함수의 이와같은 제약을
피할 수 있음
순천향대학교 정보기술공학부
이상정
28
제5장 연산자 중복
C++ 프로그래밍
예제 5.11 내장 자료형 중복 예 :
예제 5.3 수정 (1)
// Ex5_11.cpp
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y) { xval = x; yval = y; }
void get_xy(int &x, int &y)
{ x = xval; y = yval; }
friend Point operator +(Point p1,
Point p2);
// + 연산자 중복 1 : 객체 + 객체
friend Point operator +(Point p, int d);
// + 연산자 중복 2 : 객체 + 정수
friend Point operator +(int d, Point p);
// + 연산자 중복 3 : 정수 + 객체
};
// + 연산자 함수 1 : 객체 + 객체
Point operator +(Point p1, Point p2)
{
Point tmp;
tmp.xval = p1.xval + p2.xval;
tmp.yval = p1.yval + p2.yval;
return tmp;
}
// + 연산자 함수 2 : 객체 + 정수
Point operator +(Point p, int d)
{
Point tmp;
tmp.xval = p.xval + d;
tmp.yval = p.yval + d;
return tmp;
}
순천향대학교 정보기술공학부
이상정
29
제5장 연산자 중복
C++ 프로그래밍
예제 5.11 내장 자료형 중복 예 :
예제 5.3 수정 (2)
// + 연산자 함수 3 : 정수 + 객체
Point operator +(int d, Point p)
{
Point tmp;
tmp.xval = p.xval + d;
tmp.yval = p.yval + d;
return tmp;
}
pt1 = pt2 + 10; // 연산자 함수 2 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
pt1 = 88 + pt3;
// 연산자 함수 3 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
}
main()
{
Point pt1, pt2(3,8), pt3(11,2);
int x, y;
pt1 : xval => 14, yval => 10
pt1 : xval => 13, yval => 18
pt1 = pt2 + pt3; // 연산자 함수 1 + 호출
pt1.get_xy(x, y);
cout << "pt1 : xval => " << x
<< ", yval => " << y;
cout << '\n';
pt1 : xval => 99, yval => 90
pt2 + pt3 => operator +(pt2,pt3)
pt2 + 10 => operator+(pt2,10)
88 + pt3 => operator +(88,pt3)
순천향대학교 정보기술공학부
이상정
30
제5장 연산자 중복
C++ 프로그래밍
예제 5.12 단항 프렌드 연산자 함수 예 :
예제 5.7 수정
#include <iostream.h>
class Counter {
int value;
public:
Counter(int n)
{ value = n; }
Counter()
{ value = 0; }
friend void operator ++(Counter &c)
{ ++c.value; } // ++ 연산자 중복
friend void operator --(Counter &c)
{ --c.value; } // -- 연산자 중복
int operator ()()
{ return value; }
// () 연산자 중복
};
main()
{
Counter cnt1(10), cnt2;
++cnt1;
// 연산자 함수 ++ 호출
cnt2--;
// 연산자 함수 -- 호출
순천향대학교 정보기술공학부
이상정
31
cout << "cnt1 : " << cnt1() << '\n';
// 연산자 함수 () 호출
cout << "cnt2 : " << cnt2() << '\n';
// 연산자 함수 () 호출
}
cnt1 value : 11
cnt2 value : -1
++cnt1 => operator ++(cnt1)
cnt2-- => operator --(cnt2)
cnt1() => cnt1.operator ()()
제5장 연산자 중복
형 변환 함수
순천향대학교 정보기술공학부
이상정
32
C++ 프로그래밍
형 변환 함수
 객체 형을 다른 형의 객체로 변환하고자 할 때 형 변환 함수
(type conversion function)를 이용
 다음과 같은 형식으로 사용
operator 변환형()
{ return 변환값; }
• 변환형은 변환하고자 하는 형
• 변환값은 변환을 수행한 후의 변환형의 값
• 형변환 함수는 인수를 갖지 않으며 형변환을 수행하는 클래스의 멤버
함수이어야 함
• 예: operator int() { return n; }
순천향대학교 정보기술공학부
이상정
33
제5장 연산자 중복
C++ 프로그래밍
예제 5.13 형 변환 예 1
#include <iostream.h>
class Point {
int xval, yval;
public:
Point()
{ xval = yval = 0; }
Point(int x, int y)
{ xval = x; yval = y; }
operator int() { return xval * yval; }
// 형변환 함수
};
main() {
Point p1(3,6), p2(10,5);
int n;
n = 18
p2 + 10 = 60
n = p1을 수행하면 n이 정수형이므로 Point
형의 객체 p1이 정수형으로 변환되고 변환함
수 int를 실행하여 3*6의 값이 n에 저장된다.
p2 + 10을 수행하면 int 변환함수를 호출하
여 Point 형의 객체 p2가 10*5의 정수형으로
변환된 후 덧셈을 한다.
n = p1;
// 형변환 함수 호출
cout << "n = " << n << '\n';
cout << "p2 + 10 = " << p2 + 10 << '\n';
// 형변환 함수 호출
}
순천향대학교 정보기술공학부
이상정
34
제5장 연산자 중복
C++ 프로그래밍
예제 5.14 형 변환 예 2
#include <iostream.h>
#include <string.h>
class String {
char *str;
int len;
public:
String(char *s);
~String()
{ delete str; }
operator char *();
// 형변환 함수
};
String::String(char *p)
{
len = strlen(p);
str = new char[len+1];
strcpy(str,p);
}
// 형변환 함수 정의
String::operator char *()
{
char *p = new char[len+1];
strcpy(p, str);
return p;
순천향대학교 정보기술공학부
이상정
}
main()
{
String s("Hello, everybody\n");
char *p, s2[80];
p = s;
// 형변환 함수 호출
cout << "p = " << p;
strcpy(s2, s);
// 형변환 함수 호출
cout << "s2 = " << s2;
}
p = Hello, everybody
s2 = Hello, everybody
p = s를 실행하면 String 형의 객체 s가
char * 형으로 변환된 후 문자열에 대한
포인터가 저장된다. strcpy(s2, s)를 실행
하면 strcpy()의 인수가 문자열의 포인터
형이므로 String 형의 객체 s가 char * 형
35
제5장 연산자 중복
으로 변환된 인수가 전달된다.
C++ 프로그래밍
과제 1

다음 중 하나를 선택하여 연습문제를 작성하여 실행하고 프로그램 및 결과 설명
1. 연습문제 5.2
예제 4.7의 문자열 연결 cat() 멤버함수를 + 연산자 함수로, 문자열과 크기를 출력하
는 show() 멤버함수를 () 연산자 함수로 작성하라.
2. 연습문제 5.8
다음은 지수승의 결과를 생성하는 클래스의 일부분이다. 형변환 함수를 사용하여 클래스
를 완성하라. 형변환 함수는 baseexp의 결과를 정수형 으로 반환한다.
class Pwr {
int base;
int exp;
public:
Pwr(int b, int e) { base = b; exp = e; }
:
};

연습문제 과제만 게시판에 게시
•
•
과제 설명 파워포인트 파일
소스 파일(텍스트)
순천향대학교 정보기술공학부
이상정
36
제5장 연산자 중복
집합 응용 프로그램 예
순천향대학교 정보기술공학부
이상정
37
C++ 프로그래밍
3.4절 응용 예 수정
 3.4절에서 집합 연산을 위한 멤버함수를 다음과 같이 연산자
중복 함수로 각각 수정한다.
• 원소의 멤버 조사함수
• member() => [] 연산자 함수
• 원소의 삽입 함수
• insert()
=> () 연산자 함수
• 원소 제거함수
• remove() => - 연산자 함수
• 두 집합의 등가여부 조사함수
• equal()
=> == 연산자 함수
• 두 집합의 합집합 연산함수
• Union()
순천향대학교 정보기술공학부
=> + 연산자 함수
이상정
38
제5장 연산자 중복
C++ 프로그래밍
집합 클래스 정의
#include <iostream.h>
#include <stdlib.h>
// exit() 함수 선언
const MAXIMUM = 100;
enum Bool { FALSE, TRUE };
enum Error { NO, OVERFLOW };
// 최대 원소 수
// FALSE=0, TRUE=1
// NO=0, OVERFLOW=1
class Set {
int elems[MAXIMUM];
// 원소
int num;
// 집합의
public:
Set()
{ num = 0; }
// 생성자
Bool operator [](int e);
Error operator ()(int e);
friend Set operator -(Set &s, int e);
friend Bool operator ==(Set &s1, Set &s2);
friend Set operator +(Set &s1, Set &s2);
void print();
};
순천향대학교 정보기술공학부
이상정
39
원소 수
//
//
//
//
//
//
원소 e의 멤버 조사 함수
원소 e의 삽입 함수
원소 e의 삭제 함수
두 집합의 등가 여부 조사 함수
두 집합의 합집합 연산 함수
집합의 원소 출력 함수
제5장 연산자 중복
C++ 프로그래밍
[], () 연산자 함수
// 원소 e의 멤버 조사 함수
Bool Set::operator [](int e)
{
for (int i = 0; i<num; ++i)
if (elems[i] == e)
return TRUE;
return FALSE;
}
// 원소 e의 삽입 함수
Error Set::operator ()(int e)
{
for (int i = 0; i<num; ++i)
if (elems[i] == e)
return NO;
if (num < MAXIMUM) {
elems[num++] = e;
return NO;
}
else
return OVERFLOW;
순천향대학교
이상정
} 정보기술공학부
// 집합의 원소이면 TRUE 반환
// e가 이미 집합의 원소이면 정상 종료 반환
// e가 집합의 원소가 아니고 최대 원소 수를
// 초과하지 않았으면 집합에 삽입 후
// 정상 종료 반환
40
제5장 연산자 중복
C++ 프로그래밍
-, == 연산자 함수
// 원소 e의 삭제 함수
Set operator -(Set &s, int e)
{
Set res;
res = s;
// res에 s 복사
for (int i = 0; i < s.num; ++i)
if (s.elems[i] == e) {
// e가 집합의 원소이면
for (; i < s.num-1; ++i)
// 배열에서 삭제를 위해 원소의 이동
res.elems[i] = res.elems[i+1];
--res.num;
}
return res;
}
// 두 집합의 등가 여부 조사 함수
Bool operator ==(Set &s1, Set &s2)
{
if (s1.num != s2.num)
return FALSE;
for (int i = 0; i < s1.num; ++i)
if (!s1[s2.elems[i]])
return FALSE;
return TRUE;
순천향대학교 정보기술공학부
이상정
}
41
//
//
//
//
//
//
원소의 수가 같지 않으면
FALSE 반환
s2의 원소 중 하나라도
집합 s1의 멤버가 아니면
FALSE 반환, [] 연산자 함수 호출
위의 경우가 아니면 TRUE 반환
제5장 연산자 중복
C++ 프로그래밍
+ 연산자 함수, print() 함수
// 두 집합의 합집합 연산 함수
Set operator +(Set &s1, Set &s2)
{
Set res;
res = s1;
// res에 s1 복사
for (int i = 0; i< s2.num; ++i)
// res에 s2 원소 삽입
if (res(s2.elems[i]) == OVERFLOW) {
// 삽입 연산자 함수 () 호출하여 s2 원소 삽입
cout << "!! Set overflow\n";
exit(1);
}
return res;
}
// 집합의 원소 출력 함수
void Set::print()
{
cout << '{';
for (int i=0; i<num-1; ++i)
cout << elems[i] << ',';
if (num > 0)
cout << elems[num-1];
cout << "}\n";
순천향대학교 정보기술공학부
이상정
}
// 집합의 원소 출력 함수
// 마지막 원소 뒤에 , 생략
42
제5장 연산자 중복
C++ 프로그래밍
main() 함수
main()
{
Set s1,s2,s3;
// 생성자 호출
s1 = {88,33,99,77}
s2 = {10,20,30}
// 삽입 연산자 함수 () 호출
s1(88); s1(33); s1(99); s1(77);
s2(10); s2(20); s2(30);
s1 - { 77 } = {88,33,99}
20 is in s2
s1 != s2
cout << "s1 = "; s1.print();
cout << "s2 = "; s2.print();
s3 = s1 + s2 = {88,33,99,10,20,30}
s1 = s1 - 77; // 제거 연산자 함수 - 호출
cout << "s1 - { 77 } = "; s1.print();
if (s2[20]) // 멤버조사 연산자 함수 [] 호출
cout << "20 is in s2\n";
if (s1 == s2)
cout << "s1 == s2\n";
else
cout << "s1 != s2\n";
s3 = s1 + s2; // 합집합 연산자 함수 + 호출
cout << "s3 = s1 + s2 = "; s3.print();
} 순천향대학교 정보기술공학부
이상정
43
s1(88)
=> s1.operator ()(88)
s1 - 77 => operator -(s1,77)
s2[20]
=> s2.operator [](20)
s1 == s2 => operator ==(s1,s2)
s1 + s2
=> operator +(s1,s2)
제5장 연산자 중복
이진수 표현 응용 예
순천향대학교 정보기술공학부
이상정
44
C++ 프로그래밍
이진수 클래스 정의
 문자 '0','1'의 연속으로 구성된 16 비트 이진수(16 bit binary number)를
표현하는 프로그램 예
 Binary 클래스
• 16 비트 이진수를 문자 '0', '1'의 나열로 표현하기 위해서 전용부분의 자료로
16개의 문자 배열 bits[16] 선언
• bits[0]에 최상위 비트가 저장되고 bits[15]에 최하위 비트가 저장
• 예를 들어 1011001의 이진수는 아래와 같이 저장
bits
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
0
0
0
0
0
0
0
0
1
0
1
1
0
0
1
• 이진수의 값을 표현하는 각 인수에 따라 3 종류의 생성자 중복 선언
• 두 Binary 형 이진수를 더하여 그 결과를 갖는 Binary 객체를 반환하는 + 연산자
함수
• Binary 형으로 표현된 이진수를 정수형으로 변환하는 int() 형변환 함수
순천향대학교 정보기술공학부
이상정
45
제5장 연산자 중복
C++ 프로그래밍
Binary 클래스, 생성자 1
class Binary {
char bits[16];
// 16 비트 이진수 저장
public:
Binary(char *num);
// 생성자 1
Binary(int num);
// 생성자 2
Binary()
{ /* no operation */ }
// 생성자 3
friend Binary operator +(Binary n1, Binary n2);
// 두 이진수 덧셈 연산자 함수
void print();
// 이진수 출력 함수
operator int();
// 형변환 함수: Binary -> int
};
// 생성자 1: 문자열 이진수 인수
Binary::Binary(char *num)
{
int src = strlen(num) - 1;
// 인수의 비트 수
int dest = 15;
// 최하위 비트
while (src >= 0 && dest >= 0)
// 최하위 비트부터 복사
bits[dest--] = (num[src--] == '0' ? '0' : '1');
while (dest >= 0)
// bits[]의 나머지 상위 비트를 '0'으로 저장
bits[dest--] = '0';
}
순천향대학교
정보기술공학부
이상정
46
제5장 연산자 중복
C++ 프로그래밍
생성자 2
 생성자 2에서 인수가 정수형인 경우에는 이 정수형의 값을 이진수로 변환
한 후 문자 '0', '1'의 형태로 bits[] 배열에 저장
•
이진수로 변환하는 방법은 정수형의 이진수 값을 2로 나눈 후 그 나머지를 비
트로 취함
• 12를 이진수로 변환하는 과정 예
i
num
num%2
num>>1
bit[i]
15
12
0
6
‘0’
14
6
0
3
‘0’
13
3
1
1
‘1’
12
1
1
0
‘1’
13
0
0
0
0
.
.
.
.
.
.
.
.
.
.
0
0
0
0
0
이상정
47
순천향대학교 정보기술공학부
// 생성자 2: 정수형 이진수 인수
Binary::Binary(int num)
{
for (int i = 15; i >= 0; --i) {
bits[i] = (num % 2 == 0 ? '0' : '1');
// 2의 나머지 계산
num >>= 1;
}
}
제5장 연산자 중복
C++ 프로그래밍
+ 연산자 함수 (1)
 + 연산자 함수는 두 Binary 형 객체 n1, n2를 인수로 받아 각 이진수를
더한 후 그 결과 객체를 반환하는 함수
• 덧셈은 각 이진수의 최하위 비트 부터 더하고 그 결과를 res 객체의 bits[]에
저장
• 이때 캐리가 발생하면 이를 carry에 저장한 다음 비트 덧셈 때 더해 줌
• 다음은 두 이진수 n1, n2에 각각 저장된 "10", "11"의 덧셈 수행 예
i
n1.bits[i]
n2.bits[i]
value
res.bits[i]
carry
15
‘0’
‘1’
0+1+0=1
‘1’
‘0’
14
‘1’
‘1’
1+1+0=10
‘0’
‘1’
13
‘0’
‘0’
0+0+1=1
‘1’
‘0’
12
‘0’
‘0’
0+0+0=0
‘0’
‘0’
.
.
.
.
.
.
.
.
.
.
0
0
0
0
0
순천향대학교 정보기술공학부
이상정
48
제5장 연산자 중복
C++ 프로그래밍
+ 연산자 함수 (2), print() 함수
// + 연산자 함수
Binary operator +(Binary n1,
{
unsigned carry = 0;
unsigned value;
Binary res;
Binary n2)
// 캐리 비트
// 비트 덧셈 결과
// 이진수 덧셈 결과 저장
for (int i = 15; i >= 0; --i) {
value = (n1.bits[i] == '0' ? 0 : 1) +
(n2.bits[i] == '0' ? 0 : 1) + carry;
res.bits[i] = (value % 2 == 0 ? '0' : '1');
carry = value >> 1;
}
return res;
}
// 이진수 출력 함수
void Binary::print(void)
{
char str[17];
strncpy(str, bits, 16);
str[16] = '\0';
cout << str << '\n';
순천향대학교 정보기술공학부
}
// 비트 덧셈
// 덧셈 결과
// 캐리 저장
// 이진수 문자 + '\0'
// 이진수 16 비트 문자 복사
// '\0' 문자 부가
이상정
49
제5장 연산자 중복
C++ 프로그래밍
형변환 함수 int()
“1101” => 13 예
i
value << 1
bits[i]
value
0
0
‘0’
0
.
.
.
.
.
.
.
.
12
0
‘1’
1
13
2 (10)
‘1’
3 (11)
14
6 (110)
‘0’
6 (110)
15
12 (1100)
‘1’
13 (1101)
순천향대학교 정보기술공학부
이상정
// 형변환 함수
Binary::operator int()
{
unsigned value = 0;
for (int i = 0; i <= 15; ++i)
// 최상위 비트부터 정수형 변환
value = (value << 1) +
(bits[i] == '0' ? 0 : 1);
return value;
}
50
제5장 연산자 중복
C++ 프로그래밍
main(), 실행결과
main()
{
Binary b1("1100"), b2(127);
// 생성자 1,2 호출
Binary b3 = "10001", b4 = 12;
// 생성자 1, 2 호출
Binary b5;
/ 생성자 3 호출
cout
cout
cout
cout
<<
<<
<<
<<
"b1
"b2
"b3
"b4
:
:
:
:
";
";
";
";
b1 : 0000000000001100
b2 : 0000000001111111
b3 : 0000000000010001
b4 : 0000000000001100
b5 : 0000000000011101
b4 + 6 = 18
b2 - 100 = 27
b1.print();
b2.print();
b3.print();
b4.print();
- b3 = "10001", b4 = 12
=> b3("10001"), b4(12)
- b1 + b3 => operator +(b1, b3)
- (int)b4 + 6은 Binary 형 객체 b4를 형변환
b5 = b1 + b3; // 연산자 함수 + 호출
cout << "b5 : "; b5.print();
cout << "b4 + 6 = " << (int)b4 + 6
<< '\n'; // 정수 덧셈
cout << "b2 - 100 = " << b2 - 100
<< '\n'; // 정수 뺄셈, 자동 형변환
함수를 이용하여 정수형으로 변환하고 정수
덧셈을 한 후 정수의 결과를 출력한다.
- b2 - 100에서 - 연산은 정수형 만이 가능
하므로 Binary 형 b2는 자동적으로 형변환 함
}
순천향대학교 정보기술공학부
수를 호출하여 정수형으로 변환된 후 뺄셈을
이상정
51
하고 그 정수형 결과를 출력
제5장 연산자 중복
C++ 프로그래밍
과제 2
 다음 연습문제 중 하나를 작성하여 실행하고 프로그램 및
결과 설명
1. 연습문제 5.10
응용 예 5.1의 프로그램에서 두 집합간의 교집합을 구하는 멤버함수
와 한 집합이 다른 집합의 부분집합 관계인가를 판별하는 멤버함수
를 아래와 같이 연산자 함수로 작성하라.
두 집합의 교집합 연산 함수 intersect() => * 연산자 함수
부분집합 여부 조사 함수 subset()
=> >= 연산자 함수
2. 연습문제 5.11
응용 예 5.2의 이진수 클래스 Binary로 표현된 두 이진수에 대하여
논리곱(AND)과 논리합(OR) 연산을 수행하도록 각각 &, | 연산자를
중복 정의하여 프로그램하라.
 연습문제 과제만 게시판에 게시
• 과제 설명 파워포인트 파일
• 소스 파일(텍스트)
순천향대학교 정보기술공학부
이상정
52
제5장 연산자 중복