연산자 중첩(operator overloading)

<연산자 중첩(operator overloading)>

  • 연산자 오버로딩
  • 다형성을 구현하는 방법 중 하나
  • 기존에 사용하고 있는 연산자(+, -, *, /, =, %, ++, <, !, +=, <<, ==, &&, &, [ ], ( ), "," , -> 등)의 기능을 클래스에서 새롭게 정의하여 사용하는 것
  • 주로 숫자나 문자를 대상으로 하는 연산자들을 해당 클래스에서는 재정의하여 사용자들에게 편리한 프로그래밍을 제공

<연산자의 개념과 종류>

<C언어 연산자의 우선순위와 결합성>

<연산자 중첩의 필요성>

  • i+j라는 식은 두 자료 i와 j를 더하라는 의미
  • 일반적으로 i와 j는 같은 형으로 int형, float형, double형 수이다.
- 10+20, 12.5+3.7 등
  • i와 j가 문자열(i="I Love", j="You!" )이라면 i+j는 C에서는 불가능
  • C 에서는 strcat함수로 다음과 같이 구현한다.
#include <stdio.h>
#include <string.h>
int main()
{
char i[]="I Love ";
char j[]="You!";
printf("%s",strcat(i,j));
return 0;
}
  • 문자열의 경우에도 k=i+j="I Love You!"가 되면 얼마나 좋을까!
  • 2차원 좌표계의 한 점을 표현하는 경우 (2, 3), (3, 4) 등으로 x좌표값과 y좌표값으로 표현한다.
  • 수학에서는 (2, 3)+(3, 4) 하면 각 성분끼리 더해져서 (5, 7)이된 된다.
  • 프로그래밍에서 사용하는 "+"연산자에 이러한 기능은 없다.
  • +연산자가 다양한 덧셈에 사용 가능하도록 연산자의 의미를 확대 재정의하는 방법이 연산자 중첩
  • 더한다는 의미의 연산은 모두 “+”연산자 하나로 구현

<* : 선언문(구두점) vs. 실행문(연산자)>

  • 선언문: 포인터를 선언(구두점)할 때
  • 실행문: 주소로 가서 값을 가져올 때(연산자)
  • *이 선언문에서 사용되는지 실행문에서 사용되는지에 따라서 다르다
- int x=10,y;// 정수형 변수 x,y선언
- int *px; // 포인터 px선언, 선언문에서 *****는 포인터를 선언하는 구두점
- px=&x; // 정수형 변수 x의 주소를 포인터 px에 대입
- y=*px; // px가 저장하고 있는 주소로 가서 값을 가져옴
- 실행문에서 *****는 참조 연산자
  • 실행문에서 *는 포인터 변수에 저장된 주소로 가서 실제 데이터 값을 가져오는데 사용하는 참조 연산자로 간접 값(indirect value) 연산자, dereferencing 연산자라고도 함
  • px에 저장된 주소(&x)로 가서 값(x의 내용)을 가져오므로 y에는 10이 대입됨
  • *px=20; //x=20;
- 포인터 px가 가리키는 주소에 20을 대입
- px가 x의 주소를 가지고 있으므로 변수 x의 값도 바뀜
- 주소로 가서 값을 바꾸는 간접적인 방법으로 변경

<this 포인터>

  • this 포인터는 자동적으로 시스템이 만들어 주는 포인터
  • 멤버가 호출될 때 그 멤버가 속한 객체를 가르킨다.
  • 객체를 통하여 멤버를 호출할 때 컴파일러는 객체의 포인터 즉 주소를 this포인터에 넣은 다음 멤버를 호출한다.
  • this 포인터는 멤버를 호출한 객체의 const 포인터이다.
  • 멤버함수를 수행하고 나서 그 결과로 객체 자신을 되돌릴 경우 return *this라고 하면 된다.
  • 멤버함수에서 볼 때 this 포인터는 어떤 객체가 자신을 호출했는지 알고자 하는 경우
    사용한다.
  • 연산자 중첩에서 사용
  • 클래스의 멤버함수 내에서 다른 클래스에 자기 자신을 매개변수로 넘길 때 사용

<연산자 중첩 형식>

  • 단항연산자 중첩
리턴형 operator 연산자명(); //전치, ++x
리턴형 operator 연산자명(int); //후치, x++
  • 이항연산자 중첩
리턴형 operator 연산자명(매개변수);

<단항 연산자 중첩>

  • 단항 연산자에는 ++, --, -(부호)가 있다.
  • 피연산자가 하나이다
x++ 	//x를 1증가
--y  	//y를 1감소
-5	//5를 마이너스
  • 단항연산자를 중첩할 때는 매개변수가 필요 없다.

<전치 단항 연산자 중첩>

  • 전치 연산자(prefix operator)란 변수명 앞에 연산자가 오는 것을 말한다(++x, --i 등).
  • 전치 연산자는 연산이 먼저 일어나고 대입이 된다.
int x=10;
std::cout<<++x; //11
  • 전치 단항 연산자 중첩의 형식
리턴형 operator 연산자명();
void operator ++()
{
++i;
}

<x, y의 값을 하나 증가시키는 함수 만들기>

#include <iostream>
using namespace std;
class Point {
	int x;
	int y;
public:
	Point(int i, int j) { x = i; y = j; }
	int getX() { return x; }
	int getY() { return y; }
	void upPrint() {
		++x; ++y;
		cout << x << " " << y << endl;
	}
	Point up() {
		++x; ++y;
		return *this;
	}
};
int main()
{
	Point p1(3, 4);
	p1.upPrint();
	p1.up();
	cout << p1.getX() << ",";
	cout << p1.getY();
	return 0;
}

<전치 단항 연산자 중첩>

#include <iostream>
using std::cout;
class Point {
	int x;
	int y;
public:
	Point(int i, int j) { x = i; y = j; }
	int getX() { return x; }
	int getY() { return y; }
	Point operator ++()
	{
		++x;
		++y;
		return *this;
		//객체를 반환한다.
		//즉, x,y모두 리턴
	}
};
int main()
{
	Point p1(2, 3);
	++p1;
	cout << p1.getX() << ",";
	cout << p1.getY();
	return 0;
}

<전치 단항 연산자 중첩(정의를 클래스 밖으로)>

#include <iostream>
using std::cout;
class Point {
	int x;
	int y;
public:
	Point(int i, int j) { x = i; y = j; }
	int getX() { return x; }
	int getY() { return y; }
	Point operator ++(); //선언
};
Point Point::operator ++() //정의
{
	++x;
	++y;
	return *this;
	//객체를 반환한다. x,y모두 리턴
}
int main()
{
	Point p1(3, 4);
	++p1;
	cout << p1.getX() << ",";
	cout << p1.getY();
	return 0;
}

<후치 단항 연산자 중첩>

  • 후치 연산자(postfix operator)란 변수명 뒤에 연산자가 오는 것을 말한다.
x++, i-- 등
  • 후치 연산자는 대입이 먼저 일어나고 연산이 된다.
int x=10;
std::cout<<x++; //10
  • 후치 단항 연산자 중첩의 형식
리턴형 operator 연산자명(int);
void operator ++(int)
{
i++;
}

<후치 단항 연산자 중첩>

#include <iostream>
using std::cout;
class Point {
	int x;
	int y;
public:
	Point(int i, int j) { x = i; y = j; }
	int GetX() { return x; }
	int GetY() { return y; }
	Point operator --(int);
};
Point Point::operator--(int)
{
	x--;
	y--;
	return *this;
	//객체를 반환한다.
}
int main()
{
	Point p1(3, 4);
	p1--;
	cout << p1.GetX() << ",";
	cout << p1.GetY();
	return 0;
}

<이항 연산자 중첩>

  • 이항 연산자란 +, -, ×, ÷, % 등 연산자 양쪽에 피연산자가 필요한 연산자이다.
  • 이항 연산자 중첩에서는 한 개의 매개변수가 필요하다.
  • 연산자의 왼쪽 피연산자가 연산자 함수의 주체가 되고, 오른쪽 피연산자만 있으면 되기 때문이다.
  • 즉 "1+2" 라는 연산에서 왼쪽 피연산자 1이 "+"연산자의 주체이다.

<이항 연산자 중첩 : +연산자>

#include <iostream>
using std::cout;
class Point {
	int x, y; // private변수
public:
	Point() { x = 0; y = 0; }
	Point(int xx, int yy) { x = xx; y = yy; }
	Point operator +(Point ob);
	int getX() { return x; }
	int getY() { return y; }
};
Point Point::operator +(Point ob)
{
	Point temp;
	temp.x = x + ob.x;
	temp.y = y + ob.y;
	return temp;
}
int main()
{
	Point ob1(3, 5), ob2(4, 6), ob3;
	cout << ob3.getX() << "," << ob3.getY() << " ";
	ob3 = ob1 + ob2; //이항연산자 + 호출
	cout << ob3.getX() << "," << ob3.getY();
	return 0;
}

<Point클래스의 "*"연산자 중첩>

#include <iostream>
using std::cout;
class Point {
	int x, y; // private변수
public:
	Point() { x = 0; y = 0; }
	Point(int xx, int yy) { x = xx; y = yy; }
	Point operator +(Point ob);
	int getX() { return x; }
	int getY() { return y; }
};
Point Point::operator +(Point ob)
{
	Point temp;
	temp.x = x + ob.x;
	temp.y = y + ob.y;
	return temp;
}
int main()
{
	Point ob1(3, 5), ob2(4, 6), ob3;
	cout << ob3.getX() << "," << ob3.getY() << " ";
	ob3 = ob1 + ob2; //이항연산자 + 호출
	cout << ob3.getX() << "," << ob3.getY();
	return 0;
}

<Point클래스의 "=="연산자 중첩>

#include <iostream>
using std::cout;
using std::endl;
class Point {
	int x, y; //private변수
public:
	Point() { x = 0; y = 0; }
	Point(int xx, int yy) { x = xx; y = yy; }
	char operator ==(Point ob);
	int getX() { return x; }
	int getY() { return y; }
};
char Point::operator ==(Point ob)
{
	return (x == ob.x && y == ob.y) ? 'T' : 'F'; // 같으면 T, 다르면 F
}
int main()
{
	Point ob1(3, 5), ob2(4, 6), ob3(3, 5);
	cout << (ob1 == ob2) << endl; //괄호 조심
	cout << (ob1 == ob3) << endl;
	return 0;
}

<형변환 함수(type conversion function)>

  • 한 객체의 자료형을 다른 객체의 자료형으로 변환시키고자 할 때 형변환 함수(type conversion function)를 이용한다.
operator 리턴형() {return 변환값;} 
  • 리턴형은 변환하고자 하는 자료형이고 변환값은 변환을 수행할 값이다.
  • 형변환 함수는 매개변수를 갖지 않으며 형변환을 수행하는 클래스의 멤버함수이어야 한다.

<연산자 중첩의 제약>

  • 모든 연산자가 중첩될 수 있는 것은 아니다.
  • 다음 연산자들은 중첩이 불가능하다.
. .*  :: 
  • 이 연산자들은 첫 번째 피연산자로 그 객체를 갖는다는 미리 정의된 의미를
    가지므로(.*는 멤버 포인터 연산자)
?: sizeof

<연산자 중첩시 주의 사항>

  • 우선 순위를 변경할 수 없다.
  • 단항 연산자를 다항 연산자로 변경할 수 없다.
  • 임의의 새로운 연산자(**, <>)를 정의할 수 없다.
  • operator+()와 operator=()를 정의했다고 해서 operator+=()이 정의되지는 않는다.
  • 기본 자료형(int, char, float 등)에 대해서는 중첩을 허용하지 않는다.
  • "=" 연산자를 제외하고, 연산자는 파생(자식) 클래스에 상속된다.

<연산자 중첩이 부적절한 이유는?>

  • %연산자의 연산이 그 고유의 사용과 관련되어 있지 않기 때문이다
Point Point::operator %(Point ob) 
{ 
x=x+ob.x;
y=y+ob.y;
return *this;
}

<Point클래스에 대해서 이항 - 연산자를 중첩하시오.>

#include <iostream>
using std::cout;
class Point {
	int x, y; // private변수
public:
	Point() { x = 0; y = 0; }
	Point(int xx, int yy) { x = xx; y = yy; }
	Point operator -(Point ob);
	int getX() { return x; }
	int getY() { return y; }
};
Point Point::operator -(Point ob)
{
	Point temp;
	temp.x = x - ob.x;
	temp.y = y - ob.y;
	return temp;
}
int main()
{
	Point ob1(3, 5), ob2(4, 6), ob3;
	cout << ob3.getX() << "," << ob3.getY() << " ";
	ob3 = ob1 - ob2; //이항연산자 + 호출
	cout << ob3.getX() << "," << ob3.getY();
	return 0;
}

좋은 웹페이지 즐겨찾기