/ TIL

OOP - 상속과 다형성 (Inheritance & polymorphism)

OOP 개념 - 상속과 다형성 (Inheritance & polymorphism)

1. Is - a 와 Has - a (is - a & has - a relationship)

상속의 목적은 단순히 코드의 재사용(Reuse)가 아니고, 객체지향 프로그래밍에서 목표로 하는 실제 객체의 추상화를 효과적으로 하기 위함이다. 결국 상속을 잘 이해하는 것은 결국 클래스 사이의 관계를 어떻게 정의하느냐가 가장 중요한 것이다.

  • is-a 관계

먼저 is-a 관계를 살펴보면 단순히 생각하면 Class A와 Class B가 “ A is a B “ 로 표현될 수 있다면 이것은 is-a 관계이다.

Class Human 
{

}

Class Student 
{

}

위 코드의 예시를 살펴보면 사람과 학생 두가지 클래스가 존재한다. 여기서 Student 클래스와 Human 클래스의 관계에서는 is-a 관계가 성립한다. “Student is a human.”이 성립하기 때문이다. 하지만 반대의 경우인 “human is student.”는 성립하지 않기 떄문에 is-a 관계가 아니다.

is-a 관계가 성립한다면 Student 클래스는 Human 클래스에 있는 모든 기능을 포함할 수 있지만, 그 반대의 경우는 아니다.

  • has-a 관계

모든 클래스들을 is-a 관계로 설명할 수는 없다. 예를 들어 동물원 클래스와 사자 클래스, 토끼 클래스가 존재한다고 가정했을 때, 사자 is a 동물원, 동물원 is a 사자와 같은 관계는 성립이 불가능하다. 하지만 has-a 관계를 적용하면 동물원 has a 사자, 동물원 has a 토끼와 같은 관계가 성립된다. 예시는 아래와 같이 어떠한 클래스 안에 다른 클래스를 포함하고 있는 형태이다.

Class zoo
{
    private: 
    lion lions;
    rabbit rabbits;
}

2. 가상함수( Virtual Function )

virtual 키워드는 함수(메서드)에 붙일 수 있는 것인데, virtual 함수여야 상속관계에서 오버라이딩이 가능하다. virtual 키워드는 오버라이딩을 가능하게하면서, 객체지향의 다형성 개념의 핵심 역할을 한다.

이때, 가상함수 포인터를 쓰게 된다. 예를 들어 아래의 코드를 보면 아래와 같은 결과를 얻을 수 있다.

class super
{
    public :
    void print()
    {
        cout << "조상입니다." <<endl;
    }
};

class parent : public super
{
    public :
    void print()
    {
        cout << "부모입니다." <<endl;
    }
};

class child : public parent
{
    public :
    void print()
    {
        cout << "자식입니다." <<endl;
    }
};

int main() 
{
    super* superp = new super;
    parent* parentp = new parent;
    child* childp = new child;

    superp->print();
    superp=parentp;

    superp->print();
    superp=childp;

    superp->print();
}

결과 전부 다 “조상입니다”가 출력된다.

하지만 virtual 키워드를 사용하면 결과값이 다르다.

class super
{
    public :
    vitual void print()
    {
        cout << "조상입니다." <<endl;
    }
};

class parent : public super
{
    public :
    virtual void print()
    {
        cout << "부모입니다." <<endl;
    }
};

class child : public parent
{
    public :
    virtual void print()
    {
        cout << "자식입니다." <<endl;
    }
};

int main() 
{
    super* superp = new super;
    parent* parentp = new parent;
    child* childp = new child;

    superp->print();
    superp=parentp;

    superp->print();
    superp=childp;

    superp->print();
}

조상, 부모, 자식이 순서대로 나오게 된다.

3. 다중상속 ( multiple inheritance )

다중 상속은 둘이상의 클래스를 동시에 상속하는 것을 말한다. 하지만 다중 상속은 상속 개념을 완전히 이해하지 못하고 사용하면 여러가지 문제가 발생할 수 있으므로, 웬만하면 사용을 지양하도록 한다.

#include <iostream>
 
using namespace std;
 
class ParentOne {
public:
    void funcone() { cout << "ParentOne 클래스에서 funcone() 호출!" << endl; }
};
class ParentTwo {
public:
    void functwo() { cout << "ParentTwo 클래스에서 functwo() 호출!" << endl; }
};
 
class Child : public ParentOne, public ParentTwo {
public:
    void func() { funcone(); functwo(); }
};
 
int main()
{
    Child child;
 
    child.func();
    return 0;
}