강의/computer science

[computer science] c++의 operator overloading/연산자 구현하기 2편

하기싫지만어떡해해야지 2024. 10. 14. 17:27

이 게시글은

서울대학교 데이터사이언스대학원

조요한 교수님의

데이터사이언스 응용을 위한 컴퓨팅 강의를

학습을 위해 재구성하였습니다.


operator overloading 2편!

 

시시시시작..

 

 

cout에서 자주 쓰이는

<< operator의 구현을 알아보자

 

<<는 traditional하게는

오른쪽의 object에 인자로 받은 값을

append 시키는 기능을 한다

 

또한 tradition하게는

Object 자기 자신을 반환하므로

return값으로는 reference값

input으로는 오른쪽의 object를 받아준다

 

그냥 현재 벡터에 내부적으로

addElement를 해주는거고

반환값으로는 append한

자기 자신 reference를 반환해준다

 

그다음 또 하나 주목해야할게

input에 const가 있는걸 확인할 수 있는데

왜 const가 있을까?

 

literal값을 받기 위해서다

 

input으로 변수가 아닌

4, 5, "hello"같은 literal값이

들어올 수가 있는데

const를 넣어줘야 이 literal값을

정상적으로 append할 수 있다

 

 

이번엔 == operator를 보자

 

같으면 true, 다르면 false를

반환해야하기때문에

return값은 bool이다

 

operator==를 해주고

인자로는 SimpleVector를 넣어준다

 

내부에서 size가 다르면

당연히 두 SimpleVector가 아니므로

false를 반환해준다

 

그다음 요소 하나하나를 비교하면서

한개라도 다르면 false를

모든 if문에서 통과했으면

true를 반환해준다

 

 

이제 < operator를 보자

size를 check해서 더 작으면

true를 반환해주는 연산자이다

 

따라서 bool을 return으로 받고

SimpleVector를 input으로 받은 뒤

size를 가져와서 비교한 bool값을

반환해준다

 

 

bool operator에 대해 알아보자

bool operator는 지금까지의

operator 구현과는 조금 다르다

 

우선 true가 뭔지 false가 뭐인지부터

미리 정의를 해줘야한다

 

operator bool()과 같이 선언해주고

const 안에 return값을 반환해준다

 

위 ppt를 보면

size가 0보다 크면 true를 반환하고있다

 

이렇게 bool operator를 정의해주면

SimpleVector를 bool로 반환해야하는

상황이 생기면 const 내부 값을 호출하게된다

 

정확히 컴파일러가 어떤 과정을 거쳐서

bool operator를 수행하는지 보자

 

main 함수에서

if (vec1) 와 같이 코딩을 했다면

SimpleVector가 bool값으로

반환되어야하는 상황임을 인지하고

bool operator 정의부로 들어간다

그래서 내부 내용을 수행한 뒤

true/false값을 반환하게 된다

 

혹은 프로그래머가 

SimpleVector의 typecasting을

bool로 해도 호출된다

 

이런 bool operator를 사용해주는 예시로

fileInputStream이 있는데

 

file의 내용을 가져올 때

while (cin >> value)와 같은 방식으로

가져오는걸 본 적이 있을 것이다

 

저 구문을 통해서 어떻게

value값을 읽어오는지 생각해보자

 

위에서 >> operator의 구현을 살펴봤는데

>> operator는 반환값으로

object 자기 자신을 반환한다

 

따라서 cin >> value는

반환값으로 value가 append된

자기 자신을 반환한다

 

cin class의 bool operator는

지금까지 발생한 error가 있으면 false를

error가 없으면 true를 반환하도록 구현되어있는데

 

while (cin >> value)를 통해서

value를 append하고

conditional statement를 체크하기위해

bool operator 정의를 찾고

에러가 없으면 true를 반환하니까

계속해서 다음 value를 cin class안에

append하게 되는 것이다

 

그리고 value의 값이 이제 끝나거나

어떤 에러가 발생했다면

bool operator에서 false를 반환하고

while문을 탈출하게된다

 

 

 

마지막으로 range-based for loop에 대해 알아보자

 

for (auto element : vec) {

cout << elemlent << " ";

}

 

이렇게 쓰는걸 range-based for loop이라고 하는데

정확하게 말하면 operator overloading은 아니지만

유용하기 때문에 어떻게 작동하게하는지 알아보자

 

우선 이걸 사용할 수 있게 하려면

begin()과 end()를 정의해줘야한다

 

begin()은 첫 번째 포인터를 반환하고

end()는 마지막보다 1(size) 더간 포인터를 반환한다

 

이렇게 begin()과 end()가 정의되어있으면

range-based for loop를 사용할 수 있다

 

그럼 이제 이 begin()과 end()를 이용해서

compiler는 어떻게 이걸 구현하는지 살펴보자

위 ppt 코드의 예시를 통해 알아보겠다

 

우선 loop가 사용되면

vec의 begin()을 호출한다

그럼 첫 번째 포인터가 반환될텐데

이를 dereference한 걸 element라는 변수에 넣어준다

그렇게 iteration을 돌 때 마다 

포인터를 ++ 해준다

 

iteration을 돌면서

++해준 포인터가 end()와

같은지 아닌지를 체크하다가

end()와 동일하다면

for문을 탈출하도록 구현되어있다

 

 

Non-Member Functions

지금까지는 모든 operator들을

SimpleVector라는 class 내부의

method로 정의를 했다

 

그런데 class 밖에서

global scope로

non member function을

정의할 수 있는데 

유용한 방법이라 배우면 좋다고 한다

 

 

<< operator를 non-member

function으로 구현해보자

 

앞에 scope으로 넣어줬던

SimpleVector:: 를 빼준다

 

그다음 2개의 input을 받아온다

left hand side의 lhs

right hand side의 rhs

로 정의한다

 

그런다음 왼쪽에 있는

lhs에 rhs를 append해주고

lhs의 reference를 반환해준다

 

이렇게 non-member function으로

구현해주면 좋은점이 뭘까?

 

 

std같은 경우 이미 c++ 내부에서 정의가 되어있어

수정하기가 어려운데, class의 수정없이

함수를 구현할 수 있게 해준다

 

또한 implict type conversion을

허용할 수 있다

 

이게 무슨말이냐하면

string helloStr = "Hello";가 있고

helloStr == "Hello"라고 == operator를

사용해줄 경우

만약 string에서 == operator의 Input이

(const string& lhs)로 정의되어있다면

이 == operator는 호출이 안된다

 

왜냐하면 "Hello"는 string이 아닌

literal이기 때문이다

 

그래서 string class 내부가 아닌

non-member function으로

정의해주면 type conversion을

컴파일러가 해주기 때문에

위와 같은 연산이 가능해지는 것이다

 

만약 operator와 피연산자가 모두 같은데

member, non-member 둘 다

정의가 되어있다면

member function이 우선순위를 가진다

 

 

operator의 종류이고

필요에따라 정의해주면된다

 

 

이렇게 c++의 operator overloading

정리 마무리 ... -!