본문 바로가기
C++

[Effective C++] public 상속 모형은 반드시 "is-a" 를 따른다.

by Warehaus 2021. 6. 5.

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를 호출하는 코드가 있는경우, 컴파일 단계에서 우리는 그것을 인지할 수 있을 것이다.