C++ 에서 public 상속을 하는 경우 하위 클래스는 반드시 상위 클래스 개념에 속해야 됨을 의미하며 부모 A 클래스, 자식 B 클래스가 있는 경우에 'B is an A' 여야 한다는 것이다. 아래 예시코드를 살펴보자.
class Fruit { ... };
class Apple : public Fruit { ... }; // Apple is a fruit.
사과는 과일이기 때문에 위 코드는 is-a 관계가 성립한다.
이런 is-a 관계의 개념은 public 상속에만 해당하며 private, protected 는 개념이 조금 다르니 나중에 다른 포스팅에서 다뤄볼 예정이다.
is-a 관계라는 것을 숙지하고 있음에도 불구하고 의식의 흐름에 따라 코드를 구현하다보면 아래와 같은 상황에 직면한다.
class Bird
{
public:
virtual void fly();
...
};
class Chicken : public Bird
{
....
};
닭이 새이기는 하지만.. 기대하는 동작처럼 날지는 못한다. ( 체공시간이 긴 닭을 나는 것이라고 생각하지 않도록 한다. )
이런 문제를 해결하기 위해 중간에 다른 클래스를 선언해 볼 수도 있다.
class Bird
{
public:
...
};
class FlyingBird: public Bird {
virtual void fly();
...
}
class Chicken : public Bird
{
....
};
아니면 Chicken 클래스에서 fly를 구현할 때 에러를 뱉어내는 방식을 생각해 볼 수도 있지만.. 이는 실행해보기 전까지는 알 수가 없는 코드이므로 지양하는게 좋다.
class Bird
{
public:
virtual void fly();
};
class Chicken : public Bird
{
virtual void fly() {
throw error("I can't fly");
}
};
결국 Chicken이 날수 없음을 명확하게 보여주려면 아래와 같이 제약사항을 넣어주는 것이 컴파일 단계에서 에러를 확인할 수 있는 방법이 될 것이다.
class Bird{
...
};
class Chicken : public Bird {
...
};
....
Chicken* c = new Chicken();
c->fly(); // Error
위 코드에서는 fly 멤버함수를 별도로 선언하지 않아서 호출이 불가하게 만든 코드이다. Checken 인스턴스가 fly를 호출하는 코드가 있는경우, 컴파일 단계에서 우리는 그것을 인지할 수 있을 것이다.
'C++' 카테고리의 다른 글
[C++/STL] vector의 크기, length 를 구하는 방법 (0) | 2021.11.29 |
---|---|
C++ 에서 구조체를 초기화 하는 여러가지 방법 (0) | 2021.07.29 |
[Effective C++] 상속받은 비가상 함수를 파생클래스에서 재정의 하지 말자 (0) | 2021.06.11 |
[Effective C++] 내부에서 사용하는 객체에 대한 핸들은 반환하지 말자 (0) | 2021.06.02 |
[Effective C++] 변수의 정의는 최대한 늦추자 (0) | 2021.06.01 |