I'm FanJae.

[C++ 기본 연습 문제] Chapter 10. 연산자 오버로딩 I 본문

C++/Basic Practice

[C++ 기본 연습 문제] Chapter 10. 연산자 오버로딩 I

FanJae 2024. 9. 8. 22:24

1. Chapter 10. 연산자 오버로딩 I

 

1-1. 두 가지 방법의 연산자 오버로딩

 - 연산자 오버로딩을 이해하는 가장 좋은 방법은 연산자를 직접 오버로딩 해 보는 것이다.

 - 연산자를 오버로딩 하는 과정에서 자신이 이해하지 못한 부분이 드러나면서, 그 부분을 이해하게 되는 경우가 많기 때문이다. 따라서 앞서 예제 GFunctionOverloading.cpp에서 보인 Point 클래스를 대상으로 아래의 요구대로 연산자를 오버로딩 해보자.

 

① Point 클래스에 대해서 다음 조건을 만족하는 형태로 - 연산자를 오버로딩 해보자.

- 전역함수 기반으로 오버로딩

- 멤버 별 - 연산의 결과를 담은 Point 객체 반환

 

②  Point 클래스에 대해서 다음 조건을 만족하는 형태로 += 연산자와 -= 연산자를 오버로딩 해보자.

 - 멤버함수 기반으로 오버로딩

 - 연산 'pos1 += pos2'의 결과로 pos1의 멤버변수 값이 pos2의 멤버변수 값만큼 멤버 별 증가

 - 연산 'pos1 -= pos2'의 결과로 pos1의 멤버변수 값이 pos2의 멤버변수 값만큼 멤버 별 감소

 - 연산의 결과로 값이 증가 및 감소한 pos1의 객체를 반환하도록 (이왕이면 참조형으로 반환하도록) 연산자 오버로딩

 

③ Point 클래스에 대해서 다음 조건을 만족하는 형태로 == 연산자와 != 연산자를 오버로딩 해보자.

 - 둘 다 전역함수의 형태로 오버로딩

 - 연산 'pos1 == pos2'의 결과로 모든 멤버의 값이 같다면 true, 그렇지 않다면 false 반환

 - 연산 'pos1 != pos2'의 결과로 모든 멤버의 값이 같다면 false, 그렇지 않다면 true 반환

 - 연산자 == 를 먼저 오버로딩 한 다음에, 이를 이용하는 형태로 != 연산자를 오버로딩

#include <iostream>
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 << ']' << std::endl;
	}

	friend Point operator+(const Point& pos1, const Point& pos2);
	friend Point operator-(const Point& pos1, const Point& pos2);

	Point& operator+=(const Point& pos2)
	{
		this->xpos += pos2.xpos;
		this->ypos += pos2.ypos;
		return *this;
	}
	Point& operator-=(const Point& pos2)
	{
		this->xpos -= pos2.xpos;
		this->ypos -= pos2.ypos;
		return *this;
	}
	friend bool operator==(const Point& pos1, const Point& pos2);
	friend bool operator!=(const Point& pos1, const Point& pos2);
};

Point operator+(const Point& pos1, const Point& pos2)
{
	Point pos(pos1.xpos + pos2.xpos, pos1.ypos + pos2.ypos);
	return pos;
}

Point operator-(const Point& pos1, const Point& pos2) // ①
{
	Point pos(pos1.xpos - pos2.xpos, pos1.ypos - pos2.ypos);
	return pos;
}
bool operator==(const Point& pos1, const Point& pos2)
{
	if (pos1.xpos == pos2.xpos && pos1.ypos == pos2.ypos) return true;
	else return false;
}
bool operator!=(const Point& pos1, const Point& pos2)
{
	if ((pos1 == pos2) == false) return true;
	else return false;
}
int main(void)
{
	Point pos1(3, 4);
	Point pos2(10, 20);
	Point pos4(10, 20);
	Point pos5(5, 6);
	Point pos3 = pos1 + pos2;

	pos1.ShowPosition();
	pos2.ShowPosition();
	pos3.ShowPosition();

	pos5 += pos4;
	pos5.ShowPosition();
	std::cout << std::endl;
	std::cout << (pos2 == pos4) << std::endl;
	std::cout << (pos1 == pos2) << std::endl;
}

 

1-2. 단항 연산자 오버로딩

- 예제 OneOpndOverloading.cpp에서 보인 Point 클래스를 대상으로 아래의 요구대로 연산자를 오버로딩 해보자.

멤버함수의 형태로 오버로딩

 - 부호 연산자로서 -는 단항 연산자이다. 

 - 이 연산자는 피 연산자의 부호를 반전시킨 결과를 반환한다. 

 - 예를 들어서 다음 문장이 실행되면,  

- int num2 = -num1;

 - num2에는 num1과 절대값은 같지만 부호가 다른 값이 저장된다.

 - 물론 num1의 값에는 영향을 미치지 않는다. 

 - 이와 유사하게 Point 클래스를 대상으로 - 연산자를 오버로딩 해 보자.

 - 다음의 문장이 실행되면,

 Point pos2 = -pos1;

  pos2의 멤버변수는 pos1의 멤버변수 값과 다른 부호의 값으로 초기화 되도록 오버로딩 해보자.

 

② 전역함수의 형태로 오버로딩

 - ~ 연산자는 단항 연산자로서 비트단위 not의 의미를 갖는다.

 - 즉, ~ 연산자는 비트단위로 1은 0으로, 0은 1로 바꾼다.

 - 이에 우리는 Point 객체를 대상으로 다음과 같이 연산이 가능하도록 ~연산자를 오버로딩 하고자 한다.  

Point pos2 = ~pos1;

위의 ~ 연산의 결과로 반환된 객체의 xpos 멤버에는 pos1의 ypos 값이,  반환된 객체의 ypos 멤버에는 pos1의 xpos 값이 저장되어야 한다. 이번에도 하나의 답안에 위의 두 문제에 대한 답을 모두 담기로 하자.

 

#include <iostream>
using namespace std;

class Point
{
    int xpos, ypos;

public:
    Point(int x = 0, int y = 0)
        :xpos(x), ypos(y) {}
    void ShowPosition() const
    {
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    Point& operator++()
    {
        xpos += 1;
        ypos += 1;
        return *this;
    }

    Point operator-() const
    {
        Point pos(this->xpos * -1, this->ypos * -1);

        return pos;
    }

    Point operator~() const 
    {
        Point pos(this->ypos, this->xpos);
        return pos;
    }

    friend Point& operator--(Point& ref);
};

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

int main()
{
    Point pos(1, 2);
    ++pos;
    pos.ShowPosition();
    --pos;
    pos.ShowPosition();

    ++(++pos);
    pos.ShowPosition();
    --(--pos);
    pos.ShowPosition();

    pos = -pos;
    pos.ShowPosition();

    Point pos2 = -pos;
    (~pos2).ShowPosition();

    return 0;
}

 

1-3. 입력을 위한 >> 연산자의 오버로딩

① 예제 PointConsoleOutput.cpp에서 정의한 Point 클래스를 대상으로 아래의 main 함수가 보이는 대로 데이터의 입력이 가능하도록, 그리고 실행의 예에서 보이는 대로 출력이 이뤄지도록 >> 연산자를 오버로딩 하자.

int main(void)
{
    Point pos1;
    cout << "x, y 좌표 순으로 입력 : ";
    cin >> pos1;
    cout << pos1;
    
    Point pos2;
    cout << "x, y 좌표 순으로 입력 : ";
    cin >> pos2;
    cout << pos2;
    return 0;
}

 

#include <iostream>
using namespace std;

class Point
{
    int xpos, ypos;

public:
    Point(int x = 0, int y = 0)
        :xpos(x), ypos(y) {}
    void ShowPosition() const
    {
        cout << '[' << xpos << ", " << ypos << ']' << endl;
    }
    friend ostream& operator<< (ostream&, const Point&);
    friend istream& operator>> (istream&, Point&);
};

ostream& operator<<(ostream& os, const Point& pos)
{
    os << '[' << pos.xpos << ", " << pos.ypos << ']' << std::endl;
    return os;
}

istream& operator>> (istream& is, Point& pos)
{
    is >> pos.xpos >> pos.ypos;
    return is;
}
int main(void)
{
    Point pos1;
    cout << "x, y 좌표 순으로 입력 : ";
    cin >> pos1;
    cout << pos1;

    Point pos2;
    cout << "x, y 좌표 순으로 입력 : ";
    cin >> pos2;
    cout << pos2;
    return 0;
}
Comments