프로그래밍 언어 공부/C++

[Modern C++] override, final

설탕중독 2022. 7. 15. 22:32

 

[Modern C++] override, final

 

이번에는 오버라이드와 파이널에 대해 알아보자. 

중요한 개념이니 잘 숙지해두자.

 

override는 재정의라는 뜻으로 이미 존재하는 함수를 다르게 동작시키기 위해 재정의하는 것을 말한다.

이와 비슷한 개념으로 오버 로딩이 존재하는데 이미 공부했듯이 함수의 이름을 재사용하는 것을 말한다.

(즉 같은 함수 이름을 사용하지만 함수의 형태가 달라서 공존할 수 있다는 것이다.)

 

다시 본론으로 돌아와서 재정의 실습을 진행해보겠다.

 

 

1-1. 실습

두 개의 클래스를 정의하고 한쪽에서 다른 한쪽의 클래스를 상속받는 형태로 만들었다.

그리고 간단하게 문자열을 출력하는 함수를 만들었으며 자식 클래스에서 해당 함수를 재정의하는 형태이다.

메인 함수에서 포인터 클래스 타입으로 지정하고 동적할당을 이용해서 메모리 할당을 진행했으며 자식 클래스의

함수를 호출하는 모습이다. 당연하게도 출력은 자식 클래스의 함수가 호출된다.

 

하지만 여러 프로그래밍을 하다보면 한 개의 부모 클래스의 여러 자식 클래스가 존재하는 경우가 많다. 

그래서 부모 클래스의 포인터 타입으로 지정해서 코딩을 좀 더 효율적으로 하고 싶은 상황이 발생한다. 

그래서 다음과 같은 문제가 발생할 수 있다.

 

 

1-2. 실습

 효율적인 코딩을 위해 부모 클래스 포인터 타입으로 선언을 해주었지만 호출되는 함수는 재정의한 자식 클래스

함수가 아닌 부모 클래스의 함수가 호출되는 것을 알 수 있다. 이 문제를 해결하는 방법은 이전에도 공부한 적이 있는

가상 함수를 이용하는 방법이 있다.

 

 

1-3. 실습

15번 라인을 보면 부모 클래스의 함수를 가상 함수로 선언해주었다.

이렇게 가상 함수를 이용하게 되면 메인 함수에서 어떤 포인터 클래스 타입으로 선언하든 동적 할당된 원본의

함수가 호출된다. (이와 비슷한 느낌으로 최상위 부모 클래스 혹은 부모 클래스의 소멸자에는 virtual을 붙이는 것이

필수적이라는 걸 잊지말자!)

 

 

위의 코드에 아쉬운 점이 있다면 가독성적인 측면이 떨어진다는 점이다.

어느 부분에서 가독성이 떨어진다는 것일까?

 

1-3 이미지와 같은 코드에서 다른 사용자가 부모 클래스를 보지 않은 상황에서 자식 클래스만 확인했다고 가정해보자

그러면 Hellow라는 함수가 해당 자식 클래스에서 처음 시작된 함수인지 부모 클래스에도 같은 함수가 존재하는지 

알 수 있는 방법이 없다.(직접 부모 클래스의 내부를 확인하지 않는 이상) 이러한 부분에서 가독성이 떨어지며 또한

해당 함수가 어디에서 처음 시작됐는지에 대한 부분은 상당히 중요하다.

 

그러면 어느 부분부터 처음으로 함수가 시작됐는지가 왜 중요할까?

 

 

2-1. 실습
2-2. 실습

1-3 이미지의 코드에서 새로운 최상위 부모 클랙스가 추가되었다. 

Mother 클래스 또한 최상위 God 클래스를 상속받는다. 그리고 God 클래스의 함수는 가상 함수로

선언되어 있지 않다.

 

이러한 상태에서 메인 함수를 보면 최상위 클래스의 포인터 타입으로 동적 할당을 진행했다.

예전처럼 코드를 실행했지만 원본의 함수가 호출되는 것이 아닌 최상위 클래스의 함수가 호출되었다. 

최상위 클래스의 함수가 가상 함수가 아니기 때문에 이런 일이 발생하였으며, 중간의 Mother 클래스부터

가상 함수가 적용되었기 때문에 함수가 처음에 어디에서 시작되는지 아는 것이 상당히 중요하다.

 

이 문제를 해결하기 위해선 자식 클래스에서 처음 함수가 시작되는 것인지 부모 클래스에서 받아와서

사용하는 것인지 정보를 알려줄 필요성이 있다. 그래서 사용하는 것이 override이다. 이미지를 통해 알아보자.

 

 

3-1. 실습

36번 라인을 보면 함수 맨 끝에 override가 붙은 걸 확인할 수 있다. 

override가 붙게 되면 자식 클래스에서 처음 선언한 함수가 아니라 부모 클래스에서 해당 함수를

상속받아서 재정의해서 사용하고 있다는 뜻이 된다.

 

이렇게 되면 자식 클래스에서만 함수를 봐도 해당 함수가 자식 클래스에서 처음 선언한 함수가 아닌

부모 클래스에서 상속받은 함수라는 정보가 추가되는 것이다. 가독성이 좋아지며 코드가 오동작하는 것도

방지할 수 있는 안전장치인셈이다.

 

자식 클래스에서 override를 확인하고 부모 클래스로 이동했더니 똑같이 override가 있을 수 있다. 그렇다는 소리는

해당 부모 클래스 또한 상위 부모 클래스에게 함수를 상속받아서 재정의하고 있다는 뜻이다. 

 


 

이제 간단하게 final에 대해 알아보자.

final은 override와 동일하게 함수 뒤쪽에 붙여주면 되고, final을 붙이게 되면

해당 함수가 override 하고 있다는 힌트와 더불어서 해당 함수에서 마지막으로 사용할 것이고 

자식 클래스들에게 더 이상 재정의를 하게 만들어주지 않겠다는 의미이다.