항목 34 : 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
상속이라는 개념은 두 가지로 나뉩니다. 하나는 함수 인터페이스의 상속이고, 또 하나는 함수 구현의 상속입니다.
특정 클래스가 그 클래스에서 파생된 클래스에 대해 미치는 영향은 절대적입니다.
그 이유는 멤버 함수 인터페이스는 항상 상속되게 되어 있기 때문입니다.
순수 가상 함수는 두 가지 특징을 가지고 있습니다.
첫째, 어떤 순수 가상 함수를 물려받은 구체 클래스가 해당 순수 가상 함수를 다시 선언해야 합니다.
둘째, 순수 가상 함수는 전형적으로 추상 클래스 안에서 정의를 갖지 않습니다.
이 두가지를 조합해보면 하나의 결론이 나옵니다.
순수 가상 함수를 선언하는 목적은 파생 클래스에게 함수의 인터페이스만을 물려주려는 것이다.
단순 가상 함수는 순수 가상함수와 비교 할 때 몇가지 다른 면을 갖고 있습니다. 파생 클래스로 하여금 함수의 인터페이스를 상속하게 한다는 점은 똑같지만, 파생 클래스 쪽에서 오바라이드할 수 잇는 함수 구현부도 제공한다는 점이 다릅니다.
단순 가상 함수를 선언하는 목적은 파생 클래스로 하여금 함수의 인터페이스뿐만 아니라 그 함수의 기본 구현도 물려받게 하자는 것입니다.
멤버 함수가 비가상 함수로 되어 있는 경우가 있습니다. 이것은 이 함수가 파생 클래스에서 다른 행동이 일어날 것으로 가정하지 않았다는 뜻입니다. 실제로, 비가상 멤버 함수는 클래스 파생에 상관없이 변하지 않는 동작을 지정하는 데 쓰입니다. 이 함수의 역할 자체가, 미래에 만들어질 파생 클래스가 아무리 특수한 클래스라 해도 변하지 않는 동작을 수행하는 것이기 때문입니다.
비가상 함수를 선언하는 목적은 파생 클래스가 함수 인터페이스와 더불어 그 함수의 필수적인 구현을 물려받게 하는 것이다.
멤버 함수를 선언할 때, 클래스 설계를 많이 해보지 못한 사람들이 하는 실수 두 가지가 있습니다.
첫 번째, 모든 멤버 함수를 비가상 함수로 선언하는 것입니다. 이렇게 하면 파생 클래스를 만들더라도 기본 클래스의 동작을 특별하게 만들 만한 여지가 없어지게 됩니다. 특히 비가상 소멸자가 문젯거리가 될 수 있습니다(항목 7 참조).
두 번째, 모든 멤버 함수를 가상 함수로 선언하는 것입니다. 분명히 파생 클래스에서 재정의가 안 되어야 하는 함수가 있을텐데도 재정의를 해야하는 결과를 초래합니다.
꼭 잊지 말아야 할 것!
1. 인터페이스 상속은 구현 상속과 다릅니다. public 상속에서, 파생 클래스는 항상 기본 클래스의 인터페이스를 모두 물려받습니다.
2. 순수 가상 함수는 인터페이스 상속만을 허용합니다.
3. 단순(비순수) 가상 함수는 인터페이스 상속과 더불어 기본 구현의 상속도 가능하도록 지정합니다.
4. 비가상 함수는 인터페이스 상속과 더불어 필수 구현의 상속도 가하도록 지정합니다.
'언어 > C++' 카테고리의 다른 글
[Effective C++] 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물! (0) | 2020.02.05 |
---|---|
[Effective C++] 가상 함수 대신 쓸 것들도 생각해 두는 자세를 시시때때로 길러 두자 (0) | 2020.02.04 |
[Effective C++] 상속된 이름을 숨기는 일은 피하자 (0) | 2020.02.02 |
[Effective C++] public 상속 모형은 반드시 "is-a(...는 ...의 일종이다)"를 따르도록 만들자 (0) | 2020.02.01 |
[Effective C++] 파일 사이의 컴파일 의존성을 최대로 줄이자 (0) | 2020.01.31 |