Function Overloading
: 함수의 이름이 같고 그 파라미터가 다를 때 name mangling을 통해서 컴파일러가 서로 다른 함수를 만들어 주는 것.
이 코드를 compiler explorer를 통해 어셈블리 코드를 확인해 보면
function(3), function(2.7) 은 각각에 맞는 함수를 콜 해주고 있고 이름이 바뀌어 있다.
(_Z8functioni: ...) (_Z8functiond: ...) 이런 식으로 name mangling 된 것.
이렇기에 function overloading은 static polymorphism이라고도 불리는데,
그 이유는 어떤 함수가 바인딩 될 지 컴파일 시간에 결정이 되기 때문이다.
이와 비교되는 개념으로는 dynamic polymorphism이 있다.
dynamic polymorphism은 함수들이 runtime(<-> dynamic)에 바인딩 된다는 뜻이다. (static <->compile)
이 방법은 virtual이라는 키워드를 통해서 만들어 낼 수 있다.
(추후 상속에 대해 이야기 할 때 다룰 것이다.)
**function overloading은 클래스 내부의 멤버 함수로도 구현 가능하다.
<Operator overloading>
: 오퍼레이터들을 오버로딩 한다는 개념인데, *, %, /, new ,delete, [], () 등을 오버로딩 한다는 것이다.
cppreference를 참고하면
https://en.cppreference.com/w/cpp/language/operators
38개 39개의 operators와 new delete 들에 대한 operator들을 overloading 할 수 있다고 쓰여있다.
(ex1)
struct와 복소수를 사용해서 설명해보면,
복소수에는 실수부와 허수부가 있다. 그걸 double로 real, imag 로 구현하고
complexNum c1 c2 c구조체를 만들어서 출력해보면 오류가 난다.
이유는, c에서 c1+c2 부분의 operator + 가 정의되어 있지 않기 때문이다.
정의를 해 보자.
이런 식으로 정의해 줄 수 있다.
출력해 보면
마찬가지로 -, *, /, ==, != 등의 operator를 overloading 할 수 있을 것이다.
(ex2)
고양이 클래스를 만들어서 조금 더 실용적인 예시를 살펴보자.
고양이 클래스를 만들고, 나이를 돌려주는 함수와 이름을 돌려주는 함수를 만들고
print() 함수를 만들고
kitty object, nabi object를 하나씩 만들어 주고 해당하는 문자열과 1살 2살 로 생성해 주면
제대로 출력이 된다.
이제 operator overloading 을 구현해 볼 텐데,
상식적으로 kitty + nabi 또는 kitty * nabi 를 해주면 뭐가 나올지 감이 안 온다.
따라서 ==, < , << 오퍼레이터를 만들어 보겠다.
< == operator>
* < operator
이렇게 고양이 object들에 줄을 세울 수 있는 기준이 만들어진 후에,
std::vector 즉 고양이 벡터를 만들어주고 <Cat> cats; 를 추가해준다.
그리고 standard library 제공 sort function을 통해 고양이를 정렬해 줄 수 있다.
이 때 정렬의 기준은, 비교 오퍼레이터가 된다.
std::vector<Cat> cats;
// add cats
std::sort(cats.begin(), cats.end());
* << output stream operator 구현
현재 print 함수는 화면에 출력을 해 주는 std::cout 을 사용하고 있는데,
이것을 실용적으로 argument에 std::ostream& os를 받고 os에다가 출력을 해주고
이걸 실행하기 위해서 argument로 std::cout을 받아주면
똑같이 출력이 되는 것을 확인할 수 있다.
계속 무의식적으로 사용하는 std::cout 은 ostream의 하나의 종류이다.
\바로 이어서 ostream을 만들어 보면,
print 함수를 주석처리하고
이런 함수를 만들어 준 다음
int 나 string object를 출력하듯이
이렇게 호출해주면
print 함수와 똑같이 출력값이 나오는 것을 확인할 수 있다.
이러한 방식의 장점은,
print 함수에서 구현했었던 ostream을 받는 더 flexible한 print 함수일 뿐만 아니라,
OOP 중심의 더 직관적인 output을 지원해 준다는 것이다.
어떤 방식을 사용할지는 진행하는 프로젝트의 성격에 따라서 정하면 된다.
정리
complex number class 와 cat class의 operator overloading을 직접 구현해 보았다.
복소수 struct에서는 +, -, *, / 등의 사칙연산을 직관적으로 구현할 수 있다는 것을 확인했고,
고양이 class에서는 ==, <, << 등을 구현해서 더 실용적인 case에서 어떤 방식으로 operator overloading 될 수 있는지 알아보았다.
추가 정보는 cppreference의 operator overloading 을 참고할 것!
이러한 operator overloading은 생각보다 중요할 수 있는데,
어떤 operator들은 STL이 붙어서 더 강력한 C++ 기능을 지원해 주기 때문이다.
이러한 기능들을 모두 활용해서 개발한다기 보다는,
이해하기 쉬운 코드를 짠다라는 생각으로 접근하는 것이 옳은 방법이다.
'모던C++ > OOP' 카테고리의 다른 글
4. 복사, 이동 생성자 - Copy/move constructor (1) | 2022.08.06 |
---|---|
3. Member Init List - Class Constructor, Destructor (0) | 2022.08.05 |
2. Static 스태틱 멤버 (0) | 2022.08.04 |
1. OOP 란? - 객체 지향 프로그래밍 소개 (0) | 2022.07.24 |