Minwoo Dev.

[C++] 상속 본문

C++

[C++] 상속

itisminu 2024. 6. 30. 16:35
728x90
반응형
SMALL

현실에서 상속이란 단어는 부모와 자식 간의 재산 상속의 의미로 많이 사용되곤 한다.

하지만 프로그래밍에서는, 같은 기능을 가지고 있는 클래스들을 묶기 위해서 사용한다.

 

아래와 같은 상황에서 자주 사용하게 된다.

  1. 이미 만들어둔 클래스를 가지고 기능과 변수를 추가하여 새로운 클래스를 만들 때 
  2. 같은 기능을 하는 클래스가 있다면 그 두 클래스를 하나의 부모 클래스로부터 상속하게 만든다!

 

예를 들어, 에어팟의 기능을 나타내는 클래스가 존재한다고 하자.

class Airpods{
private:
    int battery;
    int volume;
public:
    Airpods(int bat, int vol):battery(bat),volume(vol){}
    void music(){
        cout << "음악 플레이 중..." << endl;
    }
    void call(){
        cout << "통화 중..." << endl;
    }
    void charge(){
        cout << "충전 중..." << endl;
    }
};

 

그리고, 무선 충전과 노이즈 캔슬링이 되는 Airpods Pro 모델도 클래스로 구현해보겠다.

 

class AirpodsPro{
private:
    int battery;
    int volume;
public:
    AirpodsPro(int bat, int vol):battery(bat),volume(vol){}
    void music(){
        cout << "음악 플레이 중..." << endl;
    }
    void call(){
        cout << "통화 중..." << endl;
    }
    void charge(){
        cout << "충전 중..." << endl;
    }
    void noiseCancel(){
        cout << "노이즈 캔슬링 중..." << endl;
    }
    void wirelessCharge(){
        cout << "무선 충전 중..." << endl;
    }
};

 

위 Airpods 클래스와 AirpodsPro 클래스는 노이즈 캔슬링과 무선 충전 기능을 제외하고는 모든 멤버변수와 함수가 똑같다.

이런 경우에, 우리는 불가피하게 코드를 중복하여 작성하게 된다.

 

코드를 중복하여 작성한다는 것은 굉장히 비효율적인 일이므로 이 부분을 상속을 통해 수정해야 한다.

 

 

 

클래스 상속

A라는 클래스를 상속하여 B라는 클래스를 만들 때, C++에서는 아래와 같이 생성한다.

class B : public A{
...
}

 

일반적인 클래스를 만들듯이 class 클래스이름 을 적고, 콜론(:)을 사용하여 상속받을 클래스를 적어주면 된다.

여기서는 A가 부모 클래스, B가 자식 클래스가 되는 것이다.

 

상속의 접근제어 지시자

상속을 할 때, public 이라는 단어가 붙어있는 것을 확인할 수 있다.

변수를 선언할 때와 같이, 세 가지가 존재한다.

 

우선, 부모 클래스에서 private으로 선언된 요소들은 상속하지 않는다. 

private은 해당 클래스 내에서만 유효한 성질을 가지기 때문이다.

따라서 상속받는 자식 클래스가 고려하는 요소는 private이 아닌 요소들에서 구분한다.

private 

private보다 넒은 범위를 가지는 접근 지정자를 모두 private 으로 상속받는다.

 

protected

protected보다 넓은 범위를 가지는 접근 지정자를 모두 protected로 상속받는다.

 

public

public보다 넓은 범위를 가지는 접근 지정자를 모두 public으로 상속받는다.

보통 public 상속을 가장 많이 사용한다.

 

 

 

그리고 주의할 점이, 상속받은 자식 클래스에서는 생성자에서 부모 클래스의 생성자를 무조건 호출해야 한다.

class B : public A{
private:
	...
public:
    B() : A(){} // 자식 클래스의 생성자에서 부모 클래스의 생성자 호출!!!
    ...
};

 

 

이러한 조건들을 고려하여 wireless 클래스와 Airpods, AirpodsPro 클래스를 생성해보겠다.

 

#include<iostream>
using namespace std;


class WirelessEarphone{ // 부모 클래스
private:
    int battery; // 멤버 변수 2개와 함수 3개를 가지고 있음
    int volume;
public:
    WirelessEarphone(int bat, int vol):battery(bat),volume(vol){}
    void music(){
        cout << "음악 플레이 중..." << endl;
    }
    void call(){
        cout << "통화 중..." << endl;
    }
    void charge(){
        cout << "충전 중..." << endl;
    }
};


class Airpods : public WirelessEarphone{ // WirelessEarphone을 public으로 상속하여 WirelessEarphone 클래스의 멤버변수와 함수를 그대로 가져옴
public:
    Airpods(int bat, int vol) : WirelessEarphone(bat, vol){} // 추가로 작성할 것이 없으므로 생성자만 정의
};

class AirpodsPro : public WirelessEarphone
{
public:
    AirpodsPro(int bat, int vol):WirelessEarphone(bat,vol){}
    void noiseCancel(){ // 추가로 작성한 함수
        cout << "노이즈 캔슬링 중..." << endl;
    }
    void wirelessCharge(){ // 추가로 작성한 함수
        cout << "무선 충전 중..." << endl;
    }
};

 

 

위처럼 작성한다면, 아래 그림처럼 상속 관계가 완성된다.

 

 

부모 객체와 자식 객체의 구조

부모 클래스를 상속하여 만든 자식 클래스는 부모 클래스의 내용을 그대로 담고 있다.

거기에 추가적으로 자식 클래스에서 정의한 부분을 가지고 있게 되는 구조이다.

주황색 선이 부모 클래스로부터 상속받은 부분, 초록색 선은 추가적으로 구현한 부분

Airpods에서는 부모 클래스에서 상속받기만 하고 따로 추가한 기능이나 변수가 없다.

따라서 상속받은 내용을 그대로 가지고 있게 된다.

 

하지만 AirpodsPro 클래스에서는 부모 클래스를 상속하고, noiseCancel()과 wirelessCharge()를 추가하였기 때문에 메모리 구조 상에서 AirpodsPro 클래스는 부모로부터 상속받은 영역과 새롭게 추가한 부분이 존재하게 된다.

 

 

자식 클래스 = 부모 클래스 + 새롭게 추가된 부분

 

 

자식 클래스 생성자에서 부모 클래스 생성자 호출

그리고, Airpods 클래스의 생성자를 보자.

class Airpods : public WirelessEarphone{
public:
    Airpods(int bat, int vol) : WirelessEarphone(bat, vol){}
};

Airpods 클래스는 현재 가지고 있는 멤버변수가 없지만, 부모 클래스인 WirelessEarphone으로부터 상속받은 멤버변수 battery와 volume 이 있다. 

그렇기에 부모 클래스의 생성자를 호출하여 부모 클래스로부터 상속받은 멤버변수를 초기화해야한다.

 

위 코드에서도 WirelessEarphone 생성자를 멤버 이니셜라이저(:)를 사용하여 호출하고 있는 것을 확인할 수 있다.

 

 

이렇듯 부모 클래스의 생성자를 통해 초기화할 값이 없을 때에도, 자식 클래스는 무조건적으로 부모 클래스를 호출해야 한다.

초기화할 값이 없는 경우라면 빈 생성자를 호출한다.

728x90
반응형
LIST