[C++][OOP] Inheritance - notation, types

 

상속: 객체 지향 프로그래밍의 재활용과 확장

상속의 개념

상속은 객체 지향 프로그래밍 (OOP)의 핵심 개념 중 하나로, 기존 클래스의 속성과 메서드를 물려받아 새로운 클래스를 생성하는 것을 의미한다. 상속을 통해 코드 재사용성을 높이고, 클래스 간의 관계를 계층적으로 표현할 수 있다.

interitance

상속, 왜 필요할까?

상속은 다음과 같은 이유로 필요하다.

  • 코드 재사용: 기존 클래스의 코드를 재사용하여 새로운 클래스를 생성할 수 있다. 이는 개발 시간을 단축하고 코드의 유지보수성을 향상시킨다.
  • 계층적 구조: 클래스 간의 관계를 계층적으로 표현하여 코드의 가독성을 높인다.
  • 다형성: 상속은 다형성을 구현하는 데 중요한 역할을 한다. 다형성은 동일한 이름의 메서드가 객체의 유형에 따라 다르게 동작하는 것을 의미한다. (지난 시간 참조)

상속, 언제 사용할까?

두 객체 사이에 "is-a" 관계가 성립할 때 상속을 사용한다. 예를 들어, "학생은 사람이다"라는 관계가 성립하므로, Student 클래스는 Person 클래스를 상속할 수 있다.



상속의 문법

C++에서 상속은 다음과 같은 문법을 사용한다.

C++
class DerivedClass: public BaseClass {
  // 멤버 변수 및 메서드
};

DerivedClass는 상속받는 클래스이고, BaseClass는 상속하는 클래스이다. public은 상속 유형을 나타낸다.


상속 유형

상속 유형은 기본 클래스의 멤버에 대한 접근 권한을 결정한다. C++에서는 다음과 같은 세 가지 상속 유형을 제공한다.

  • public 상속: 기본 클래스의 public 멤버는 파생 클래스에서 public 멤버로, protected 멤버는 protected 멤버로 유지된다.
  • protected 상속: 기본 클래스의 public 멤버와 protected 멤버는 파생 클래스에서 protected 멤버로 유지된다.
  • private 상속: 기본 클래스의 public 멤버와 protected 멤버는 파생 클래스에서 private 멤버로 유지된다.
각각의 역할에 대해서는 class 관련 글에서 언급하였으므로 생략하겠다.
즉, 위의 관계에 따라 기본 클래스의 private 멤버는 항상 파생 클래스에서 접근이 불가능하고, 나머지 관계는 가장 포함 범위가 작은(private < protected < public) 순으로 파생 클래스의 멤버의 type이 된다.


이제 예제를 통해 자세히 살펴보도록 하겠다.

예시

C++
class Base {
private:
  int m_private;
protected:
  int m_protected;
public:
  int m_public;
  int GetPrivate() { return m_private; }
};

class Derived : public Base {
public:
  void AccessMembers() {
    // m_private = 10; // Error: private 멤버에 직접 접근 불가
    m_protected = 20; // OK: protected 멤버에 접근 가능
    m_public = 30; // OK: public 멤버에 접근 가능
    int privateValue = GetPrivate(); // OK: public 멤버 함수를 통해 private 멤버에 접근
  }
};

위 코드에서 Derived 클래스는 Base 클래스의 private 멤버인 m_private에 직접 접근할 수 없다. 그러나 Base 클래스가 제공하는 public 멤버 함수인 GetPrivate()을 통해 m_private 값을 얻을 수 있다.



상속 위계의 중요성

한편, 상속은 클래스 간의 계층적 관계를 나타내기 때문에, 상속 위계를 유지하는 것이 중요하다. 상속 위계를 유지하지 않으면 코드의 가독성이 떨어지고, 예상치 못한 동작이 발생할 수 있다.

다음 예제는 상속 위계를 유지하지 않은 경우 발생하는 문제를 보여준다.

C++
class Person {
public:
  void Eat() { cout << "Eat" << endl; }
};

class Student: public Person {
public:
  void Study() { cout << "Study" << endl; }
};

class Teacher: public Person {
public:
  void Teach() { cout << "Teach" << endl; }
};

int main() {
  Student s1;
  Teacher t1;
  Person* p_arr[] = { &s1, &t1 };
  for (int i=0; i<2; i++) {
    p_arr[i]->Study(); // Error: Person 클래스에는 Study 메서드가 없다.
  }
  return 0;
}

위 코드에서 Person 클래스에는 Study 메서드가 없기 때문에, p_arr[i]->Study() 호출은 에러를 발생시킨다.


마치며

이번 포스팅에서는 상속의 개념, 필요성, 사용 시점, 문법, 상속 유형, 상속 위계의 중요성에 대해 알아보았다. 기본적인 부분에 대해 다뤘으니 다음 시간에는 생성자, 소멸자 등 상속에 대해 더 자세히 알아보고자 한다.


추천글:

[C++][OOP] Polymorphism - operator overloading
(https://hyeondev.blogspot.com/2024/10/coop-polymorphism-operator-overloading.html)

[C++][OOP] Class - definition, struct, constructor, destructor
(https://hyeonb.blogspot.com/2024/10/coop-class-definition-struct.html)

[C++][OOP] Class - UML diagram, relationship
(https://hyeondev.blogspot.com/2024/10/coop-class-uml-diagram-relationship.html)

hyeon_B

안녕하세요! AI 기술을 이용해 더 나은 세상을 만들어 나가고 싶은 과기원생 Hyeon이라고 합니다. 저는 앞으로 인공지능 시대에는 지식을 '활용'하는 능력이 중요해질 것이라고 생각합니다. 대부분의 일들은 인공지능이 뛰어난 모습을 보이지만, 인공지능은 데이터로 부터 연관관계를 학습하기 때문에 지식들을 새로 통합해서 활용하는 능력이 부족합니다. 인공지능이 뉴턴 전에 만들어졌다면 사과가 떨어지는 이유에 대답하지 못했을 것이고, 아인슈타인 전에 만들어졌다면 중력이 어떻게 생기는지 설명하지 못했을 것입니다. 따라서 앞으로 우리는 '본질'을 탐구하고 그 본질로부터 다른 곳에 적용하며 인공지능을 현명하게 활용해야 할 것입니다. 함께 인공지능 시대를 준비합시다!

댓글 쓰기

다음 이전

POST ADS1

POST ADS 2