CPP/씹어먹는 c++

[Cpp 개념공부] 상속 (함수 오버라이딩, 상속 접근지시자)

뜨거운 개발자 2023. 2. 10. 10:27

상속 (Inheritance)

  • 다른 클래스의 내용을 그대로 포함 할 수 있다. -즉 복사 붙혀넣기를 줄일 수 있는 방법
  • 부모 - 자식 클래스 또는 기반-파생 클래스라고 부른다. (부모가 여럿일 수 있기 때문에 기반 파생 클래스가 더 적절하다)ex) class Derived : public Base ===⇒ Derived 가 Base를 public 형식으로 상속 받았다.
  • 초기화 리스트에서 파생클래스는 기반클래스의 생성자를 먼저 호출하고 파생클래스의 초기화를 한다.
  • 만약 명시적으로 호출 하지 않았다면 기반클래스의 디폴트 생성자가 호출된다.

예시

class Derived : public Base 
{   
    std::string s;   
    public:   Derived() : Base(), s("파생") 
    {// Derived의 생성자 부분은 당연히도 Base()의 생성자를 먼저 호출해야만 한다.!!! 
        std::cout << "파생 클래스" <<  std::endl;     // Base 에서 what() 을 물려 받았으므로    
        // Derived 에서 당연히 호출 가능하다   
        what(); 
    } 
};

class Derived : public Base : Derived 는 Base를 public형식으로 상속 받았다.

이렇게 되면 Derived 에서는 Base에 있는 함수와 Base에 있는 변수들을 전부다 가지고 간다 즉 사용을 하는 개념과는 다르게 아에 코드를 한번 더 가져온다 라고 생각하면 된다.

Derived() : Base(), s("파생")

초기화 리스트에서 Base 를 통해 기반의 생성자를 먼저 호출하게 됩니다.

참고로 기반 클래스의 생성자를 명시적으로 호출하지 않을 경우 기반 클래스의 디폴트 생성자가 호출됩니다.

부모(기반) 클래스에도 함수가 있고 자식(파생)클래스에도 같은 이름의 함수가 있는 경우 어떨까?

컴파일러에서 문제가 발생하지는 않는다. 따라서 멀리 있는 부모까지 않고 자식에서 호출 할 때 자식에 함수가 있다면 자식을 호출하게 된다.

함수 오버라이딩

  • 기반 클래스에 있는 함수와 파생 클래스에 있는 함수가 이름과 인자까지 같아도 가까운곳에 있는 함수를 실행한다.
  • 이 경우 기반 클래스에 있는 함수를 파생 클래스에서 오버라이딩했다고 한다.(오버로딩이 아니다.)
  • 즉 파생 클래스에서 아에 이름과 인자가 같은 함수를 만들어서 기반 클래스의 함수가 호출이 되는게 아니라 파생클래스의 함수가 호출되도록 하는 것이다.

 

protected(상속 접근지시자)

💡
private 멤버 변수들은 어떠한 경우에도 자기 클래스 외에는 접근 할 수 없다.!! (상속 받은 친구가 있어도 기반클래스의 private에 접근할 수 없는건 마찬가지이다.
💡
하지만 파생 클래스에서 기반 클래스의 멤버변수에 접근해야 할 일이 있다.
💡
public과 private의 중간에 있는 protected 라는 접근 지시자를 사용한다.
💡
protected : 상속받은 클래스에서는 접근 가능하나 다른곳에서는 접근 불가능 한 데이터

 

상속 접근 지시자

  • public으로 상속 : 기반클래스 접근 지시자 변화 없다.(public 은 public으로 private는 private로)
  • protected로 상속 : 파생 클래스 입장에서 public이 protected로 바뀌고 나머지는 유지된다.
  • private로 상속 : 파생클래스 입장에서 모든 접근지시자들이 private 가 된다.

왼쪽 코드의 경우 접근이 아무 문제가 없었지만 오른쪽 코드의 경우 컴파일 오류가 발생하게 된다.

private로 접근하는 이유

  • 재사용성: 개인 상속을 사용하여 파생 클래스의 기본 클래스에서 코드를 재사용할 수 있으므로 코드 중복을 줄이고 유지 관리성을 향상할 수 있습니다.
  • 추상화: 파생 클래스의 인터페이스를 기본 클래스의 인터페이스와 분리하여 개인 상속을 통해 추상화를 개선하고 파생 클래스 사용자에게 구현 세부 정보를 숨길 수 있습니다.
  • 코드 구성: 비공개 상속은 코드를 더 작고 관리하기 쉬운 부분으로 분해하여 코드를 구성하고 이해하고 유지 관리하기 쉽게 만들 수 있습니다.
  • 다형성: 개인 상속은 파생 클래스의 구현 세부 정보를 노출하지 않고 파생 클래스의 개체를 기본 클래스의 개체로 처리할 수 있는 다형성의 한 형태로 사용할 수 있습니다.

왜 private로 상속을 하는지를 이해하지 못했는데 아래 예시처럼 다른 클래스에서 상속을 할 수 있기 때문이다.

#include <iostream> 
using namespace std;  
class Animal 
{   
    public:   
    void makeSound() 
    {    
        cout << "Some generic animal sound" << endl;  
    } 
};

class Dog : private Animal 
{  
    public:  
        void bark()
        {      
            makeSound(); 
        }
}; 

int main() 
{ 
    Dog A; 
    A.bark(); 
}

이 예시를 보면 된다.

#include <iostream>  
class Base 
{   
    public:
        void what() {  std::cout <<"private 실행되네" <<   std::endl; } 
}; 

class Derived : private  Base
{ 
    public: 
    void	xx() 
    { 		
        what();
    } 
}; 

int main() 
{ 	
    Derived A; 
    A.xx(); 
}

그러나 실제 현업에서 사용하는 코드들을 보면 대부분 상속의 99% 정도는 public으로 되기 때문에 사실 상속은 아주 특수한 목적을 가지고 있지 않는한 public으로 상속해주는 것이 좋다.


Uploaded by

N2T
728x90