티스토리 뷰

반응형

10-1 연산자 오버로딩의 이해와 유형

 

operator+라는 이름의 함수

 

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


class Point
{
private:
	int xpos, ypos;
public:
	Point(int x = 0, int y = 0) :xpos(x), ypos(y)
	{}
	void ShowPosition() const
	{
		cout << '[' << xpos << ", " << ypos << ']' << endl;
	}
	Point operator+(const Point& ref)
	{
		Point pos(xpos + ref.xpos, ypos + ref.ypos);
		return pos;
	}
};

int main(void)
{
	Point pos1(3, 4);
	Point pos2(10, 20);
	Point pos3 = pos1.operator+(pos2);

	pos1.ShowPosition();
	pos2.ShowPosition();
	pos3.ShowPosition();
	return 0;
}

 

[3, 4]

[10, 20]

[13, 24]

 

Point pos3=pos1+pos2;

이 문장은 컴파일이 되며, 덧셈 저장결과가 리턴된다.

 

pos1+pos2가 pos1.operator+(pos2)의 다른 표현일거다.

->무언가 변환의 규칙이 있을 것이다.

 

 

대화로 풀어보는 연산자 오버로딩

-객체도 기본 자료형 변수처럼 덧셈, 뺄샘, 곱셈 등을 하려고 한다.

-'operator' 키워드와 '연산자'의 이름을 묶어 함수를 호출한다.

-Point pos3=pos1+pos2를 pos1.operator+(pos2)로 바꿔서 해석

 

 

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

-멤버함수에 의한 연산자 오버로딩

-전역함수에 의한 연산자 오버로딩

 

            

pos1+pos2 ->pos1.operator+(pos2)

               ->operator+(pos1, pos2) 전역변수로 선언된 경우

 

 

오버로딩이 불가능한 연산자의 종류

. 멤버 접근 연산자

.* 멤버 포인터 연산자

:: 범위 지정 연산자

?: 조건 연산자(3항 연산자)

sizeof (바이트 단위 크기 계산)

typeid RTTI 관련 연산자

static_cast 형변환 연산자

dynamic_cast 형변환 연산자

const_cast 형변환 연산자

reinterpret_cast 형변환 연산자

 

C++의 문법규칙을 보존하기 위해 오버로딩을 제한한다.

 

 

오버로딩이 가능한 연산자

=

()

[]

->

이들은 객체를 대상으로만 쓰이기 때문에, 멤버 기반으로만 오버로딩을 허용한다.

 

 

연산자 오버로딩 하는데 있어서의 주의사항

1) 본래의 의도를 벗어난 오버로딩은 좋지않다.

pos1+pos2을 덧셈 외에 다른 결과가 나오는 건 좋지 않다.

 

2) 연산자의 우선순위와 결합성은 바뀌지 않는다.

3) 매개변수의 디폴트 값 설정이 불가능하다.

피연산자의 자료형에 따라 오버로딩 한 함수의 호출이 결정되는데, 매개 변수를 디폴트로 줄 수 없다.

 

4) 연산자의 순수 기능까지 뺏을 수는 없다.

int oprator+라 쓰고 *연산을 정의할 수 없다.

 

 

연산자 오버로딩이라 이름을 붙은 이유를 이해하셨나요?

 

int num=3+4;

Point pos3= pos1+pos2;

함수가 오버로딩 되면 전달되는 인자에 따라서 호출되는 함수가 달라진다.

연산자가 오버로딩 되면, 피연산자의 종류에 따라서 연산의 방식이 달라진다.

 

 

10-2 단항 연산자의 오버로딩

 

증가, 감소 연산자의 오버로딩

1증가 연산자 ++

2감소 연산자 --

 

++pos;//pos는 Point 객체

 

++pos -> pos.operator++(); 멤버함수

          -> operator++(pos); 전역함수

로 변환된다.

 

 

전위증가와 후위증가의 구분

 

++pos -> pos.operator++();

pos++ -> pos.operator++(int);

 

--pos -> pos.operator++();

pos-- -> pos.operator--();

 

int를 전달하면 후위증가가 가능하다.

여기서의 int는 일반적인 자료형이 아니라 전위증가와 후위증가를 구분하느 역할을 한다.

 

const Point operator--(Point& ref, int)
{
	const Point retobj(ref);
	ref.xpos -= 1;
	ref.ypos -= 1;
	return retobj;
}

 

 

반환형에서의 const 선언과 const 객체

 

const 함수 내에서는 const 함수의 호출만 허용하도록 한다.

int main(void)

{

 const Point pos(3,4);

 const Point &ref=pos;

 

}

연산을 이용한 값이 새로 pos에 덧붙여지는 것이 아니다.

 

 

다시 본론으로 돌아와서

const Point operator--(Point& ref, int)
{
	const Point retobj(ref);
	ref.xpos -= 1;
	ref.ypos -= 1;
	return retobj;
}
int main(void)
{
	Point pos(3, 5);
	(pos++)++;
	(pos--)--;
}

 

위의 두 문장은 const로 선언되어 있지 않기 때문에 에러를 발생시킨다.

 

 

10-3 교환법칙 문제의 해결

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


class Point
{
private:
	int xpos, ypos;
public:
	Point(int x=0, int y=0):xpos(x),ypos(y)
	{}
	void ShowPosition() const
	{
		cout << '[' << xpos << ", " << ypos << ']' << endl;
	}
	Point operator*(int times)
	{
		Point pos(xpos * times, ypos * times);
		return pos;
	}
};

int main(void)
{
	Point pos(1, 2);
	Point cpy;

	cpy = pos * 3;
	cpy.ShowPosition();

	cpy = pos * 3 * 2;
	cpy.ShowPosition();
	return 0;
}

[3, 6]

[6, 12]

 

cpy = pos*3;

cpy= 3*pos; // 3.operator*(pos)로는 해석 불가능!

 

 

교환법칙의 성립을 위한 구현

 

Point operator*(int times, Point&ref)

{

 Point pos(ref.xpos*times, ref.ypos*times);

 return pos;

}

Point operator*(int times,Point&ref)

{

 return ref&times;

}

 

로 오버로딩을 하면 해결된다.

 

 

 

10-4 cout, cin 그리고 endl의 정체

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

namespace mystd
{
	using namespace std;

	class ostream
	{
	public:
		void operator<<(char* str)
		{
			printf("%s", str);
		}
		void operator<<(char str)
		{
			printf("%c", str);
		}
		void operator<<(int num)
		{
			printf("%d", num);
		}
		void operator<<(double e)
		{
			printf("%g", e);
		}
		void operator<<(ostream& (*fp)(ostream& ostm))
		{
			fp(*this);
		}
	};

	ostream& endl(ostream& ostm)
	{
		ostm << '\n';
		fflush(stdout);
		return ostm;
	}
	ostream cout;
}

int main(void)
{
	using std::cout;
	using mystd::endl;
	
	cout << "Simple String";
	cout << endl;
	cout << 3.14;
	cout << endl;
	cout << 123;
	endl(cout);
	return 0;
}

함수가 오버로딩되어서 어떤 것을 넣어도 출력이 그대로 된다.

 

#include <iostream>

namespace mystd
{
	using namespace std;

	class ostream
	{
	public:
		ostream& operator<<(char* str)
		{
			printf("%s", str);
			return *this;
		}
		ostream& operator<<(char str)
		{
			printf("%c", str);
			return* this;
		}
		ostream& operator<<(int num)
		{
			printf("%d", num);
			return*this;
		}
		ostream& operator<<(double e)
		{
			printf("%g", e);
			return*this;
		}
		ostream& operator<<(ostream& (*fp)(ostream& ostm))
		{
			return fp(*this);
			
		}
	};

	ostream& endl(ostream& ostm)
	{
		ostm << '\n';
		fflush(stdout);
		return ostm;
	}
	ostream cout;
}

int main(void)
{
	using std::cout;
	using mystd::endl;
	
	cout << 3.14 << endl << 123 << endl;
}

 

 

<<, >> 연산자의 오버로딩

 

int main(void)

{

 Point pos(3, 4);

 cout<<pos<<endl; //[3, 4] 출력

}

 

cout<<pos가 되려면 pos도 오버로딩이 되어 있어야한다.

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함
반응형