[C++] 인터페이스 상속과 구현 상속(2)


인터페이스만을 물려주는 상속에 이어

인터페이스뿐만 아니라 그 함수의 기본 구현도

물려받는 상속에 대해 알아보도록 하자.


1. 멤버 함수의 인터페이스 만을 상속받고 싶은 경우

2. 함수의 인터페이스 및 구현을 모두 상속받고 그 상속받은

구현이 오버라이드가 가능하게 만들었으면 할 경우

3. 또한 인터페이스와 구현을 상속받되 어떤 것도

오버라이드할 수 없도록 막고 싶은 경우




class Shape{

public:

virtual void draw const = 0;                ----- 1번

virtual void error (const string& msg);----- 2번

int objectId() const;                            ----- 3번


}


인터페이스뿐만 아니라 그 함수의 기본 구현을 상속 받는것

즉, 위의 예시에서 2번에 해당하는 경우가 되겠다.


단순 가상 함수로 선이 되어 있는데, 순수 가상 함수와

비교했을 때 몇가지 다른 면을 가지고 있다. 파생 클래스가

인터페이스를 상속받는 것은 똑같지만, 파생 클래스 쪽에서

오버라이드 할 수 있는 함수 구현부도 제공한다는 점이다.




virtual void error (const string& msg); ----- 2번

이 함수가 뜻하는 것은 실행 중에 에러가 났을 때

이 함수를 제공하는 것은 모든 파생 클래스가 해야 하는

 일이지만, 그렇다고 각 파생 클래스마다 똑같은 방법으로

에러를 처리할 필요는 없다는 것이다. (재정의 가능)


또한 Shape 클래스에서 제공하는 기본 에러 처리

(기본 구현)를 사용해도 된다는 의미도 있다. ( 구현 상속 )




하지만 단순 가상 함수에서 함수 인터페이스와 기본 구현을

한꺼번에 지정하도록 내버려 두는 것은 위험할 수도 있다.

아래의 예제를 보도록 하자.




모든 비행기는 fly함수를 상속 받아

각각의 비행 방식을 설정할 수 있으며

기본 동작으로 움직일 수도 있다.


위의 두 비행기는 비행 동작이 같기 때문에

코드 중복을 피하기 위해 기본 비행 원리를

Airplane::fly 함수의 본문으로 제공했다.


여기까지는 객체 지향 기술의 장점을

모두 빼다박은 훌륭한 코드이다.




하지만 여기서 비행 방식이 완전히 다른

ModelC라는 비행기가 들어왔다.

때문에 fly 함수를 재정의 해야 하지만

만약 이부분을 깜빡했다면 큰 문제로 이어질 수 있다.


여기서 문제는 Airplane::fly 함수가 기본 동작을

구현해서 가지고 있다는 점이 아니라, ModelC가

기본 동작을 물려받는 데 아무런 제약이 없다는 것이다.

이 문제를 해결하기 위해서는 크게 두가지 방법이 있다.




01. 

가상 함수의 인터페이스와 그 가상 함수의

기본 구현을 잇는 연결관계를 끊어 버리는 방법




이제 fly함수가 순수 가상 함수로 선언되어 있기 때문에

파생 클래스에서는 무조건 이 함수를 재정의 해야한다.

ModelA , ModelB는 비가상 함수인 ( 구현만을 물려 받는 )

deflultFly를 fly함수 내에서 호출하면 된다.


ModelC는 fly를 재정의하지 않으면 안되기 때문에

앞서 보았던 재정의를 깜빡하는 일은 이제 할 수 없다.




02.

순수 가상 함수의 구현을 통해

함수의 선언부, 정의부를 나누는 방법




순수 가상 함수가 들어왔다는 것 말고는

이전 설계와 원리 모두 똑같다. 순수 가상 함수가

구체 파생 클래스에서 재선언되어야 한다는

사실을 활용하되, 자체적으로 순수 가상

함수의 구현을 구비해 두는 것이다.




하지만 이 방법은 01 방법과 다르게

함수의 각기 다른 보호 수준을 부여할 수 있는

융통성이 날아가 버린다. protected 영역에 있던

defaultfly가 순수 가상 함수의 영역으로 들어왔기 때문


저번 포스팅에서 순수 가상 함수의 구현을 주는 일은

단순 가상 함수에 대한 기본 구현을 보다 안전하게

제공하는 메커니즘으로 활용할 수 있다고 했는데

바로 이 부분이라 할 수 있겠다.




얘기가 길어졌지만, 이번 포스팅의 주제는

단순 가상 함수를 선언하는 목적은 파생 클래스로 하여금

함수의 인터페이스뿐만 아니라 그 함수의 기본 구현도

물려받게 하자는 것이다.



다음 포스팅에서는 인터페이스와 더불어 그 함수의

필수 구현을 물려받게하는 경우, 3번에 해당하는

내용을 다루도록 하겠다.


Point!!

단순 가상 함수는 인터페이스 상속과 더불어

기본 구현의 상속도 가능하도록 지정합니다.






+ Recent posts