13.2 Overloading the arithmetic operators using friend functions

주홍영·2022년 3월 18일
0

Learncpp.com

목록 보기
145/199

https://www.learncpp.com/cpp-tutorial/overloading-the-arithmetic-operators-using-friend-functions/

c++에서 가장 흔히 사용되는 operator는 arithmetic operator일 것이다
(+, -, *, /) 그리고 위와 같은 산술 연산자들은 모두 2항 연산자이다

overload operator의 방법에는 3가지 정도가 있다
1. member function way
2. friend function way
3. normal function way

먼저 이번 섹션에서는 friend function way에 대해서 살펴보자

Overloading operators using friend functions

예시를 보자

#include <iostream>

class Cents
{
private:
	int m_cents {};

public:
	Cents(int cents) : m_cents{ cents } { }

	// add Cents + Cents using a friend function
	friend Cents operator+(const Cents &c1, const Cents &c2);

	int getCents() const { return m_cents; }
};

// note: this function is not a member function!
Cents operator+(const Cents &c1, const Cents &c2)
{
	// use the Cents constructor and operator+(int, int)
	// we can access m_cents directly because this is a friend function
	return Cents{c1.m_cents + c2.m_cents};
}

int main()
{
	Cents cents1{ 6 };
	Cents cents2{ 8 };
	Cents centsSum{ cents1 + cents2 };
	std::cout << "I have " << centsSum.getCents() << " cents.\n";

	return 0;
}

friend function을 선언하는 것처럼 friend 키워드를 사용해
Cents를 return type으로 갖는 operator+ 함수이름으로 overloading 하고 있다

그리고 return에서 anonymous type을 이용해 값을 전달하고 있다
그리고 저러한 initialize방식은 Cents의 constructor로 정의되어 있음을 알 수 있다

마찬가지로 subtraction operator도 정의해 준다

#include <iostream>

class Cents
{
private:
	int m_cents {};

public:
	Cents(int cents) : m_cents{ cents } { }

	// add Cents + Cents using a friend function
	friend Cents operator+(const Cents &c1, const Cents &c2);

	// subtract Cents - Cents using a friend function
	friend Cents operator-(const Cents &c1, const Cents &c2);

	int getCents() const { return m_cents; }
};

// note: this function is not a member function!
Cents operator+(const Cents &c1, const Cents &c2)
{
	// use the Cents constructor and operator+(int, int)
	// we can access m_cents directly because this is a friend function
	return Cents{c1.m_cents + c2.m_cents};
}

// note: this function is not a member function!
Cents operator-(const Cents &c1, const Cents &c2)
{
	// use the Cents constructor and operator-(int, int)
	// we can access m_cents directly because this is a friend function
	return Cents(c1.m_cents - c2.m_cents);
}

int main()
{
	Cents cents1{ 6 };
	Cents cents2{ 2 };
	Cents centsSum{ cents1 - cents2 };
	std::cout << "I have " << centsSum.getCents() << " cents.\n";

	return 0;
}

유사한 방식으로 operator overloading을 진행했다

Overloading operators for operands of different types

function overloading 처럼 같은 operator+라는 함수 이름에
여러 버젼의 implementation을 구현할 수 있다

#include <iostream>

class Cents
{
private:
	int m_cents {};

public:
	Cents(int cents) : m_cents{ cents } { }

	// add Cents + int using a friend function
	friend Cents operator+(const Cents &c1, int value);

	// add int + Cents using a friend function
	friend Cents operator+(int value, const Cents &c1);


	int getCents() const { return m_cents; }
};

// note: this function is not a member function!
Cents operator+(const Cents &c1, int value)
{
	// use the Cents constructor and operator+(int, int)
	// we can access m_cents directly because this is a friend function
	return { c1.m_cents + value };
}

// note: this function is not a member function!
Cents operator+(int value, const Cents &c1)
{
	// use the Cents constructor and operator+(int, int)
	// we can access m_cents directly because this is a friend function
	return { c1.m_cents + value };
}

int main()
{
	Cents c1{ Cents{ 4 } + 6 };
	Cents c2{ 6 + Cents{ 4 } };

	std::cout << "I have " << c1.getCents() << " cents.\n";
	std::cout << "I have " << c2.getCents() << " cents.\n";

	return 0;
}

위 코드에서 보면 operator+에 int와 Cents를 연산할 수 있는 operator overloading을 했다
order가 바뀔수도 있으므로 두가지 버젼이 정의되었다

참고로 둘 중 하나의 order만 정의한다면 다른 order로 정의된 연산은 사용할 수 없다
즉 엄밀하게 order가 고려된다는 것을 주의하자

Another example

#include <iostream>

class MinMax
{
private:
	int m_min {}; // The min value seen so far
	int m_max {}; // The max value seen so far

public:
	MinMax(int min, int max)
		: m_min { min }, m_max { max }
	{ }

	int getMin() const { return m_min; }
	int getMax() const { return m_max; }

	friend MinMax operator+(const MinMax &m1, const MinMax &m2);
	friend MinMax operator+(const MinMax &m, int value);
	friend MinMax operator+(int value, const MinMax &m);
};

MinMax operator+(const MinMax &m1, const MinMax &m2)
{
	// Get the minimum value seen in m1 and m2
	int min{ m1.m_min < m2.m_min ? m1.m_min : m2.m_min };

	// Get the maximum value seen in m1 and m2
	int max{ m1.m_max > m2.m_max ? m1.m_max : m2.m_max };

	return { min, max };
}

MinMax operator+(const MinMax &m, int value)
{
	// Get the minimum value seen in m and value
	int min{ m.m_min < value ? m.m_min : value };

	// Get the maximum value seen in m and value
	int max{ m.m_max > value ? m.m_max : value };

	return { min, max };
}

MinMax operator+(int value, const MinMax &m)
{
	// call operator+(MinMax, int)
	return { m + value };
}

int main()
{
	MinMax m1{ 10, 15 };
	MinMax m2{ 8, 11 };
	MinMax m3{ 3, 12 };

	MinMax mFinal{ m1 + m2 + 5 + 8 + m3 + 16 };

	std::cout << "Result: (" << mFinal.getMin() << ", " <<
		mFinal.getMax() << ")\n";

	return 0;
}

위의 코드에서 main함수의 mFinal안에 m1 + m2 + 5 + 8 + m3 + 16이라고 되어 있다
이는 MinMax mFinal = (((((m1 + m2) + 5) + 8) + m3) + 16) 라고 해석할 수 있으며
순차적으로 계산을 operator 연산을 진행한다는 것을 알 수 있다

그리고 return에서 { m + value } 와 같이 괄호만 존재하는데 이는
MinMax{ m + value } 와 같은 말이다
저런 방식으로 하는 것을 처음 봤지만 가능은 한가보다

Implementing operators using other operators

위의 코드를 보면 operator+(int, MinMax)를 정의할 때 operator+(MinMax, int)를 호출하여
redundancy를 최소화하였다
불필요하고 번거롭게 다시 작성할 필요없이 order가 상관없는 연산이라면 위와 같이 정의할 수 있다

profile
청룡동거주민

0개의 댓글