객체지향 언어인 C++에서 상속은 여러가지 면에서 비중있게 다루어져야 하는 부분이다. 상속의 의의와, 상속 문법 그리고 프로그램 내에서 상속을 통해서 구현하고자 하는 것들 등등..
하지만 실제로 보통 프로그래머들은 상속의 기능 중 아주 일부분만을 기계적으로 사용한다. 그도 그럴 것이 제대로된 클래스를 설계하는 것은 특정 능력자들의 손에 의해서 이루어지고 일반적으로 프로그래머들은 그것을 사용하거나 아주 간단한 상속만 만들어 사용하는데 익숙해져 있기 때문이다.
어찌되었건 상속의 다양한 주제들 중에 가장 기본적인 상속의 접근 지정자에 대해서 간단이 언급하겠다.
3가지 상속 접근 지정자
우선 상속 접근 지정자로는 public, private, protected의 세가지가 있습니다. 그리고 위 표를 보기 전에 각 접근 지정자의 특성을 알아야 합니다.
쉽게 이해하기 위해서 코드의 영역을 (기반 클래스의 정의부, 파생 클래스의 정의부) 로 나누어 보겠습니다. 그리고 몇가지 예를 언급해 보겠습니다.
① 먼저 기반 클래스의 정의부에서 public으로 정의된 속성에 대해서는 파생 클래스의 정의부에서 접근이 가능하며 파생클래스의 객체를 통해서도 접근이 가능합니다.
② 기반 클래스의 정의부에서 private로 정의된 속성에 대해서는 파생 클래스의 정의부에서 접근이 불가하며 파생클래스의 객체를 통해서도 접근이 불가합니다. 또한 기반 클래스의 객체를 통해서도 접근이 불가하며 오직 기반 클래스의 정의부 내에서만 접근 가능합니다.
(보통 특정 클래스의 객체를 통해서 접근이 가능하다는 표현을 외부에서 접근이 가능하다고 표현하기도 합니다.)
③ 기반 클래스의 정의부에서 protected로 정의된 속성에 대해서는 파생클래스의 정의부에서 접근이 가능하지만 외부에서는 접근이 불가합니다.(기반클래스나 파생클래스의 객체를 통해서 접근이 불가)
위 코드를 보면 접근이 불가한 변수 아래 빨간 물결 밑줄이 그어져 있습니다.
이렇게 private(내에서 정의된) 속성은 파생 클래스 또는 외부에서의 접근을 철저하게 제한하는 형태의 접근자입니다.(위 코드 멤버변수 a 참고)
반면에 public은 파생 클래스 또는 외부에서의 접근을 모두 허용하는 형태의 접근자이며 protected는 파생 클래스의 접근은 허용하지만 외부에서의 접근은 제한합니다. (위 코드 멤버변수 c 참고)
이렇게 속성의 접근 정도를 설정하기 위해 접근지정자가 사용됩니다.
※ 기반 클래스의 private 멤버를 초기화 시키는 방법은 여기를 참고하시기 바랍니다.
위에서는 속성에 접근 지정자를 설정하는 것을 다루었다면 이번에는 상속시 접근 지정자에 따른 특성을 살펴보겠습니다.
보통 우리는 클래스를 상속 받을 때 앞에서 본 코드 같이 public 상속을 사용합니다.
class Derived : public Base {
...
};
이렇게 상속을 할 때 상속할 클래스 앞에 접근 지정자를 써 주는데 속성에 접근지정자를 지정했을 때와 약간 의미의 차이가 있습니다.
public 상속 : 기반 클래스의 속성 접근 지정자의 의미를 그대로 두어 상속한다. 단 원래 private인 속성은 접근 불가다.
private 상속 : 기반 클래스의 속성 접근 지정자의 의미를 모두 private로 만든다. 단 원래 private인 속성은 접근 불가다.
protected 상속 : 기반 클래스의 속성 접근 지정자의 의미를 최소 protected로 만든다.( public -> protected, 나머지는 그대로, 단 원래 private인 속성은 접근 불가다.)
※ 원래 private로 접근 지정된 속성은 자신의 클래스 내에서만 접근 가능하면 파생 클래스건 외부에서건 무조건 접근 불가입니다.
※ 외부에서 데이터의 접근성이 제일 낮은 private가 가장 데이터 보안이 높다고 하면 public은 가장 보안이 낮습니다. 이런 측면에서 최소라는 의미를 사용하였습니다.
이게 무슨 황당한 소리냐? 하실 수도 있으므로 예를 통해 살펴보겠습니다.
왼쪽 코드에서 public 상속을 했을 때는 파생 클래스의 객체 A를 통해서 멤버변수 b에 접근이 가능했습니다.
그런데 오른쪽 코드에서 protected 상속으로 변경했을 때 파생 클래스의 객체 A에서 멤버 변수 b로 접근이 불가한 것을 알 수 있습니다.
왜냐면 public 속성이 protected 속성으로 변경되어 상속되기 때문이죠.
그런데 private 상속은 좀 특수하게 이해해야 합니다. 왜냐면 애초에 기반 클래스의 private 멤버는 파생 클래스에서 접근이 불가합니다.
따라서 private 상속을 했을 때도 애초에 private 속성은 접근이 불가합니다.
하지만 public, protected 속성은 private 속성으로 변경되는데 이 때는 파생 클래스에서 private 속성으로 상속받았다는 뜻이므로 파생클래스의 정의부에서는 접근 가능합니다. 이해를 돕기 위해 3단계 상속의 경우를 예를 들어 보겠습니다.
위 코드는 Base 클래스를 Derived 클래스가 상속받고, Derived 클래스를 Derived2 클래스가 상속받는 구조입니다.
왼쪽 코드는 두 번의 상속 모두 public 상속을 하였습니다. 어찌되었건 private 속성인 a는 Derived, Derived2 클래스에서 접근 불가하죠.
그리고 오른쪽 코드처럼 Derived 클래스에서 Base 클래스를 상속할 때 Private 상속으로 바꿔봤습니다. Derived 클래스의 정의부에서는 아무런 변화도 없죠? 왜냐면 애초에 private 속성은 a는 접근 불가 그대로며, 나머지 public 속성 b와 protected 속성 c는 private 속성으로 상속되었기 때문입니다. 좀 더 쉬게 말해서 속성 b와 c는 Derived 클래스에서 private 속성으로 정의된 것 처럼 행동한다는 것입니다.
이렇게 같은 private지만 애초에 기반클래스에서 private인 녀석과 기반 클래스에서는 private가 아니었는데 private 상속이 된 녀석은 다르다는 것을 구별해야합니다!
따라서 Derived를 public 상속한 Derived2에서 속성 b와 c에 접근 불가인 것입니다. 왜냐면 앞서 언급했듯이 속성 b와 속성 c는 Derived 클래스에서 private로 접근 지정된 것 처럼 행동하기 때문입니다.
참 간단한 것 같지만 복잡하네요..