본문 바로가기

Programming/C&CPP

C++ 클래스 상속

반응형

OOP의 주된 특징 중에 하나는 상속과 그를 통해 구현 되는 다형성입니다.

상속은 현실 세계에서 부모에서 자식에게 전해지는 것과 동일한 의미입니다.

부모 클래스의 정보는 자식에게 전해집니다.

상속은 기존의 클래스를 확장해서 사용할 수 있으며 클래스에 다형성을 부여합니다.

또한, 공통된 속성을 하나로 묶어줄 수 있다는 장점이 있습니다.

일반적으로 C++에서의 상속 클래스는 다음과 같이 표현됩니다.

#include <iostream>
using namespace std;

class Parent
{
private:
	int m_a, m_b;
public:
	Parent(int a = 0, int b = 0)
	{
		m_a = a;
		m_b = b;
	}
	void printnum()
	{
		cout << "a : " << m_a << " b : " << m_b << endl;
	}
};

class Inherit : public Parent
{
private:
	char m_c;
public:
	Inherit(int a = 0, int b = 0, char c = NULL) :Parent(a, b)
	{
		m_c = c;
	}
	void printchar()
	{
		cout << "character : " << m_c << endl;
	}
};

void main()
{
	Parent Par(2, 3);
	Inherit Inh(4, 5, 'a');
	Inh.printchar();
	Inh.printnum();
}

상속을 받을 때는 액세스 지정을 설정할 수 있는데, public, protected, private이 존재합니다.

class Inherit : public Parent 코드에는 public이라고 되어 있습니다.

public 지정으로 상속을 받으면 부모의 멤버 변수나 메소드의 보안 속성을 그대로 따릅니다.

public은 자식에서도 public이 되고, protected는 자식에서도 protected입니다.

private 속성은 어떤 액세스 지정을 하더라도 상속이 되지 않습니다.

protected는 public, protected 모두 자식에서 protected 속성이 됩니다.

같은 원리로 private는 모두 private 속성으로 상속이 됩니다.

코드에서 눈여겨 볼 부분은 자식 클래스의 생성자 부분인데 초기화 리스트로 부모의 생성자를 호출합니다.

자식 클래스는 부모의 멤버 변수를 직접 초기화할 수 가 없습니다.

현재 부모 클래스의 멤버 변수가 private이기 때문에 접근이 불가능하기 때문입니다.

그래서 부모 클래스의 생성자를 호출해서 멤버 변수 초기화를 위임하는 것입니다.

만약 생성자를 이런 식으로 바꾸면 오류를 뱉어낼 것입니다. 

Inherit(int a = 0, int b = 0, char c = NULL)
{
	m_a = a;
	m_b = b;
	m_c = c;
}

비주얼 C++ 2013 환경에서는 이런 오류를 뱉어냅니다.

error C2248: 'Parent::m_a' : cannot access private member declared in class 'Parent'

error C2248: 'Parent::m_b' : cannot access private member declared in class 'Parent'

그래서 상속에서 클래스의 생성 순서는 부모 클래스에서 자식 클래스 순이 됩니다.

클래스의 파괴 순서는 이 반대로 자식 클래스에서 부모 클래스의 순서로 진행이 됩니다.

자식 클래스는 직접 privave 속성의 값을 참조할 수는 없지만 public: 에 정의된

printnum()함수를 이용해서 간접적으로 접근해서 출력은 가능합니다.

상속은 트리 형식으로 표현이 가능합니다.

MFC의 상속 관계도(클래스 계층도)는 상당히 복잡하게 되어있습니다.

상속받은 클래스는 다시 다른 클래스의 부모가 될 수 있습니다.

상속시에는 주의할 점이 있는데 다중 상속이 될 가능성이 존재한다는 점입니다.

다른 언어에서는 이런 다중 상속을 아예 막는 경우도 있습니다.

A,B,C,D가 있고 A가 최상위 부모 B,C가 A의 파생(자식) 클래스이고,

D가 B,C를 상속 받으면 D는 A를 두번 상속 받게 된다는 것입니다.

즉, class B : public A, class C : public A, class D : public b,public c 이런 구조입니다.

class D가 2개의 클래스에서 상속을 받는 것은 전혀 문제가 되지 않습니다.

C++은 언어에서 다중 상속을 허용하고 있기 때문입니다.

다만 이럴 때 A의 멤버 변수 a가 있을 때 이것을 접근하려고 하면 오류를 뱉어냅니다.

A에게 상속 받은 a라는 변수가 불분명하다고 판단하기 때문입니다.

그래서 이런 상속 계층을 주의 해야합니다.

자식은 부모 클래스의  함수를 재정의해서 쓸 수도 있는데 바로 오버라이딩(overriding)입니다.

오버라이딩을 하면 부모 클래스의 기능과는 다른 기능을 정의할 수 있습니다.

상속은 클래스의 공통점을 추출해서 상위 클래스를 정의하는 것으로

클래스의 유지보수를 더 쉽게 해줍니다.

반응형