상속

pjh5365·2023년 6월 13일
0

[C++]

목록 보기
1/6
post-thumbnail

상속

  • 상속은 객체 지향 언어의 본질적인 특성이므로 상속이 없다면 객체지향이라 할 수 없다.
  • 객체 지향 언어에서 상속은 부모의 유전자를 자식이 물려받는 상속과 유사하다.
  • C++ 에서는 부모클래스를 기본클래스 자식클래스를 파생클래스라 부른다.
  • C++ 에서는 다중상속을 허용한다.

상속의 목적

간결한 클래스 작성

동일한 코드가 여러 클래스에 중복이 된다면 클래스의 유지 보수에 번거로운 일이 발생하므로 상속을 통해 하나의 클래스만 수정하면 동일한 코드를 사용하는 클래스들 역시 수정이 가능하다.

클래스 간의 계층적 분류 및 관리의 용이함

상속은 서로 관련된 클래스를 계층관계로 표현하여 존재하는 클래스들의 구조적인 관계파악을 쉽게 해준다.

클래스 재사용과 확장을 통한 소프트웨어의 생산성 향상

상속선언방법

class 파생클래스 : 접근지정자 기본클래스명 {
    상속받는 내용
};

ex)	Animal을 상속받는 Dog 클래스 
class Dog : public Animal {
  
}
  • 이때 사용하는 접근 지정자는 기본 클래스의 범위를 정한다. private 로 선언을 한다면 protected, public 멤버들이 모두 범위가 private로 제한되어 상속되고 protected 로 선언을 한다면 public 멤버들이 protected 멤버로 바뀌어 상속된다.
  • 기본클래스의 private 멤버들은 상속이 되지만 기본클래스에서의 접근만 가능하다.
  • 상속시 접근 지정자를 생략한다면 자동으로 private 상속이 된다.

Point 클래스를 상속받는 ColorPoint 클래스

#include <iostream>
#include <string>

using namespace std;

class Point {
    int x, y;
public:
    void set(int x, int y) {
        this->x = x;
        this->y = y;
    }
    void showPoint() {
        cout << "(" << x << ", " << y << ")" << endl;
    }
};

class ColorPoint : public Point {
    string color;
public:
    void setColor(string color) {
        this->color = color;
    }
    void showColorPoint();
};

void ColorPoint::showColorPoint() {
    cout << color << " : ";
    showPoint();
}

int main() {
    Point p;
    ColorPoint cp;
    cp.set(3, 4);
    cp.setColor("GREEN");
    cp.showColorPoint();
}

실행결과

GREEN : (3, 4)

ColorPoint는 상속을 통해 Point의 멤버를 자신의 멤버로 확장한다. ColorPoint의 멤버들은 Point의 private 멤버 외에 모든 멤버를 접근할 수 있다.

업 캐스팅

  • 업 캐스팅이란 파생 클래스의 객체를 기본 클래스의 포인터로 가르키는 것을 말한다. (기본 -> 파생)
  • 사람을 동물로 볼 수 있는 것 처럼 업 캐스팅은 파생클래스의 객체를 기본클래스의 객체처럼 다룰 수 있게 한다.
  • 업 캐스팅은 파생클래스가 기본클래스의 멤버를 포함하기 때문에 가능하다.

다운 캐스팅

  • 다운 캐스팅이란 기본클래스 포인터가 가리키는 객체를 파생클래스의 포인터로 가르키는 것을 말한다. (파생 -> 기본)
  • 업 캐스팅과는 다르게 다운 캐스팅으로 갈 때에는 반드시 강제 타입변화가 필요하다.
  • 만약 파생클래스에는 있지만 기본클래스에 없는 멤버에 접근을 하게 된다면 컴파일 오류는 없지만 해당 객체의 공간에는 기본클래스의 멤버만 존재하기 때문에 오류가 발생하여 비정상 종료가 발생한다.

상속에서의 생성자와 소멸자

  • 파생클래스 객체가 생성될 때는 기본클래스의 생성자가 먼저 실행되고 이후에 파생클래스의 생성자가 실행된다.
  • 소멸자는 생성될 때 와 반대로 파생클래스의 소멸자가 먼저 실행된 이후 기본클래스의 소멸자가 실행된다.
  • 파생클래스가 기본클래스의 생성자를 선택하지 않은 경우 기본클래스의 기본생성자가 실행이 된다. 따라서 기본생성자가 없다면 오류가 발생하게 된다.

생성자를 선택하는 방법

#include <iostream>

using namespace std;

class A {
public:
    A() {
        cout << "A기본생성자 실행" << endl;
    }
    A(int x) {
        cout << "A매개변수 생성자 실행 : " << x << endl;
    }
};
class B : public A {
public:
    B() {
        cout << "B기본생성자 실행" << endl;
    }
    B(int x) : A(x) {
        cout << "B매개변수 생성자 실행 : " << x << endl;
    }
};

int main() {
    B b(5);
}

실행결과

A매개변수 생성자 실행 : 5
B매개변수 생성자 실행 : 5

파생클래스에서 기본클래스의 생성자를 선택하려면 파생클래스의 생성자 뒤에 기본클래스의 생성자를 입력해준다.

다중 상속

  • 다중상속은 하나의 파생클래스가 여러 클래스를 동시에 상속받는 것으로 다중상속을 통해 여러 기능을 통합한 클래스를 만들 수 있다.
  • 다중상속으로 클래스를 생성할 때는 클래스 선언부에서 접근 지정자와 함께 기본클래스를 , 로 나열한다

다중 상속의 문제점

  • 한 기본클래스를 상속받은 두개의 파생클래스를 다중 상속받는 또다른 하나의 파생클래스가 만들어 진다면 기본클래스의 멤버가 중복되어 상속되는 경우가 발생한다.
    멤버 중복을 피하기 위해 virtual 키워드를 사용하여 가상상속을 선언한다.
  • virtual 키워드는 컴파일러에서 파생클래스의 객체가 생성될 때 기본클래스의 멤버 공간을 오직 한번만 할당하고, 이미 할당되어 있다면 공유하도록 지시한다. 따라서 멤버가 중복되어 상속되는 경우를 피할 수 있다.

0개의 댓글