본문 바로가기
C++

[C++]Class 상속

by Junk_Seo 2018. 1. 30.
반응형

Class 상속

class에서 상속은 상위 개념을 하위 개념이 상속받아서 사용하는 것입니다. 

그리고 상속을 사용하기 위해서는 추상화와 구체화의 구분이 명확해야 합니다. 

따라서 class 상속을 공통적인 부분을 구현하여 상속받아 사용한다는 것은 틀린 개념이고, 이렇게 사용할 경우 추후에 수정이나 추가를 해야 할 경우 구현해야 하는 부분이 많아지고 복잡해집니다. 

 

Class 상속 사용 방법

상위 class(부모 class)를 하위 class(자식 class)가 상속받기 위해서는 하위 클래스 이름 옆에 ' : '와 접근 제한자, 그리고 상속할 class 이름을 붙여주시면 됩니다.

class C_PARENT
{
    ...
};
class C_CHILD : public C_PARENR
{
    ...
};

 

Class 상속의 특징(다형성)

상위 개념으로 하위 개념을 지칭하는 것이 class 상속의 특징입니다. 

즉, 상위 class(부모 class)를 포인터 형식으로 사용하여 상속받은 하위 class(자식 class)를 관리하는 것이 주요 기능입니다.

이러한 것을 다형성이라고 합니다.

 

Class 상속의 메모리 관점

부모 class가 상속받은 자식 class를 지칭하는 것이 가능한 이유는 메모리를 잡는 방식 때문입니다. 

자식 class는 생성하면 먼저 부모 class를 메모리에 잡고 그다음에 자신의 메모리를 잡기 때문에  부모 class로 자식 class를 지칭하는 것이 가능합니다.

                                  

위 그림처럼 C_PARENT class를 상속하는 C_CHILD class를 생성하면 메모리에 빨간 네모 부분처럼 C_PARENT와 C_CHILD를 메모리를 잡습니다. 따라서 C_CHILD의 메모리 중에서 C_PARENT 부분으로 인해 C_PARENT가 C_CHILD를 지칭하여 사용하는 것이 가능합니다.

 

오버라이딩(overriding)

오버라이딩이란 부모 class에 선언된 멤버 함수를 자식 class에서 동일하게 선언하는 것입니다.

이때 함수의 형태는 동이하며 함수의 내용만 class에 따라 달라집니다.

class C_PARENT
{
    ...
public:
    void func();
};
class C_CHILD : public C_PARENR
{
    ...
public:
    void func();
};

위의 코드와 같이 파란색 부분으로 부모 class와 자식 class에 같은 함수가 멤버로 있는 것이 오버라이딩 됐었다고 합니다.

이러한 오버라이딩이 class 상속에서 다형성을 구성하는 핵심 기능입니다. 

하지만 단순히 저렇게만 선언한다면 struct와 namespace의 기능을 가진 class에서는 자기 namespace에 존재하는 멤버만 호출 가능하기 때문에 다형성을 사용할 수 없습니다.

int main()
{
	C_PARENT cParent;
	C_CHILD cChild;
	cParent.func();              //C_PARENT의 func()
	cChild.func();               //C_CHILD의 func()
	cChild.C_PARENT::func();     //C_PARENT의 func()
	return 0;
}

위 코드처럼 오버라이딩 된 멤버 함수를 호출할 경우 cParant는 C_PARENT에 정의된 func() 함수를 cChild는 C_CHILD에 정의된 func() 함수를 호출하게 됩니다. 

C_CHILD는 C_PARENT를 상속하고 있기 때문에 func() 함수를 호출할 때 부모 class인 C_PARENT::라는 namespace를 지정할 경우 C_PANRET에 정의된 함수를 호출할 수 있습니다.

하지만 C_PARENT가 C_CHILD에 정의된 func() 함수를 호출할 수는 없습니다. 왜냐하면 C_PARENT의 접근 권한은 C_PARENT class안까지이기 때문입니다. 따라서 C_PARENT 범위 밖에 있는 C_CHILD class에 접근할 수 없습니다. 

이러한 이유 때문에 virtual 키워드가 필요합니다.

 

virtual 키워드(가상 함수)

오버라이딩이 class 상속에서 다형성을 구성하는 핵심 기능이지만 단순히 오버라이딩만 구현할 경우 다형성을 구성할 수 없습니다. 이러한 이유로 virtual 키워드를 사용합니다.

class C_PARENT
{
    ...
public:
    virtual void func();
};
class C_CHILD : public C_PARENR
{
    ...
public:
    virtual void func();
};

위 코드의 빨간 부분인 virtual 키워드를 오버라이딩 하여 사용할 함수의 앞에 붙여서 사용합니다. 

virtual의 기능은 원래 부모 class는 namespace 범위 밖에 있는 자식 class의 오버라이딩 된 함수에 접근할 수 없기 때문에 호출이 불가능 하지만 virtual 키워드가 붙는다면 상속 관계에서 가장 마지막으로 상속받는 class의 오버라이딩 된 함수에 강제로 링크를 걸어서 부모 class가 자식 class의 오버라이딩 된 함수를 호출하도록 하게 합니다. 

이를 통해서 상속 관계에서 다형성을 구성할 수 있게 됩니다.

 

****

virtual 키워드는 가장 상위 class의 오버라이딩 된 함수 앞에만 붙여주면 되지만 코드의 가독성을 위해 자식 class의 오버라이딩 된 함수에도 모두 virtual 키워드를 붙여주는 것이 좋습니다.

****

int main()
{
	C_PARENT* pParent = unllptr;
	C_CHILD cChild;
	pParent->func();             //C_CHILD의 func()
	return 0;
}

위 코드처럼 부모 class를 통해 자식 class를 지칭한 다음 부모 class를 통해 자식 class의 오버라이딩 된 함수를 호출하게 됩니다.

이 처럼 오버라이딩 된 함수에 virtual 키워드가 붙은 함수를 가상함수라고 합니다.

반응형