학생과 선생의 공통점 = " 사람" 이라는 것

→ 그래서 공통된 사람의 "속성"을 상속받도록 하는 것

상속을 받은 base클래스의 멤버변수는 base의 메서드를 통해 관리를 해줘야한다.

→ 생성자생성에서 derived 클래스에서 base의 멤버변수는 base의 생성자를 호출해야 하는것

private 는 클래스 외부에서 접근을 못한다.

→ 상속에서도 적용이다. 자식클래스 또한 접근이 불가능하다. 하지만 protected는 자식에서는 가능하다. 혹은 base클래스의 멤버변수를 public으로 해서 상속과 클래스 외부에서 사용이 가능하도록 할 수도 있다.

하지만 캡슐화를 권장하기에 private를 사용하는 것을 추천한다.

예제 실습


Base

  1. 언뜻 보면 Base는 string을 다루는 클래스라고 생각하면 된다. 그 외의 string을 받아 새로운 이름으로 덮어씌우는 setName 메서드와 현재 이름을 반환하는 getName 메서드를 통해 데이터를 관리하는 클래스이다.

그렇기에 기본적으로 다른 클래스에 상속하기 적합한 형태로 구성되어 있어 Derived의 학생과 선생의 클래스의 속성 중 하나인 이름에 상속을 부여해서 코드를 효율적으로 다룰 수 있게 된다.

#pragma once
#include <string>
#include <iostream>

class Person {
private:
    std::string m_name;

public:
    Person(const std::string& name_in = "No Name")
        :m_name(name_in){}

    void setName(const std::string& name_in) {
        m_name = name_in;
    }

    std::string getName() const { return m_name; }

    void doNothing() const {
        std::cout << m_name << " is doing nothing" << std::endl;
    }
};

Derived

  1. Derived 클래스에서의 "학생" 과 "선생" 은 공통적인 성질 [이름] 을 가지고 있다. 그래서
    이름을 다루는 메서드 [이름 새로 바꾸기] , [이름 반환받기] 또한 [사람] 클래스에서 몰아 넣어서 관리를 하기 쉽도록 할 수 클래스 내부에 메서드를 설정하게 되면 클래스를 수정하기도 그리고 다루기도 쉬워진다.
  2. Derived 클래스에서는 학생은 공부를 선생은 가르침을 하기 때문에 base가 되는 Person과는 다른 Derived 클래스 만의 행동을 추상화하여 생성할 수 있다.
    학생은 멤버변수인 "지능" 과 그리고 "공부 메서드" 를 가지고
    선생은 멤버변수는 없고 "가르침 메서드"를 가지고 있다.

결론적으로는 Base는 상속받는 것들 중에서 공통된 것을 부여받고 공통된 것을 다루는 메서드를 다루게 된다. Derived는 Dervied만의 속성을 다루기만 하면된다. 그로 인해 계속 상속을 해도 각자 담당하는 부분을 담당하는 속성을 나타내는 클래스만으로 접근하기에 수정 또한 담당 클래스를 조금 수정하면 유지 보수가 편하다.

Student Class

#pragma once

#include <string>
#include "Person.h"

class Student : public Person {
private:
    int m_intel;

public:
    Student(const std::string& name_in = "No Name",const int & intel_in = 0)
        : Person{ name_in }, m_intel(intel_in){}

    void setIntel(const int& intel_in) {
        m_intel = intel_in;
    }

    int getIntel() { return m_intel; }
    void studing() {
        std::cout << getName() << "is studing" << std::endl;
    }
    friend std::ostream & operator << (std::ostream& out, const Student& student) {
        out << student.getName() << " " << student.m_intel;
        return out;
    }

};

Teacher Class

#pragma once
#include "Person.h"

class Teacher :public Person{
private:
public:
    Teacher(const std::string& name_in = "No Name")
        : Person(name_in) {

    }

    void teaching() {
        std::cout << getName() << "is teaching" << std::endl;
    }

    friend std::ostream & operator << (std::ostream& out, const Teacher& teacher) {
        out << teacher.getName();
        return out;
    }
};

'프로그래밍 언어 > C++' 카테고리의 다른 글

[따라 배우는 C++] 11.1 상속의 기본(1)  (0) 2020.10.22

상속(Inheritance)란?


클래스에서 상속을 쓰는 이유는 "프로그램 코드의 재사용" 을 목적으로 한다.

직업을 표현하는 객체를 생성한다고 가정하자. 직업이 다양하기에 "판사" , "프로그래머" , "교사" 등 하루 종일 나열할 수 있을 정도로 직업을 무수히 많다.

이런 직업을 표현할 수 있는 객체를 만들 때 직업은 사람이 가지는 직무를 의미하기에 사람의 특징인 "키" , "성별", "몸무게", "나이"공통된 속성이 있다. 이런 공통된 것을 "Person" 클래스로 만들고 "job" 의 클래스에 상속을 하여 코드를 재사용해 직업 마다 모든 걸 매순간 타이핑 하지 않고 상속을 통해 시간을 단축하고 효율적인 작업을 하기 위함으로 사용 된다.

 

 

상속 방법 C++


상속을 받는 클래스 이름을 derived , 상속을 하는 클래스 이름을 Mother 이라고 칭하겠다.

이럴 경우 C++에서는 아래와 같이 표현으로 선언할 수 있다.

// 형태 : Class derived : 접근지정자(public,private,protected) Mother

// ex)
Class Teacher : public Person{
    ...
};

만일 같은 이름의 멤버함수가 있을때는 어떨까?

#include <iostream>
using namespace std;

class Person {
    int age;
public:
    void foo() {
        cout << "Person" << endl;
    }
};

class Teacher : public Person {
    int salary;
public:
    void foo() {
        cout << "job" << endl;
    }
};

int main() {
    Teacher t;
    Person p;

    p.foo(); // Person이 출력될 것이다.
    t.foo(); // Person? job?


    return 0;
}

위의 코드에서 t.foo()는 분명 Person이 출력될것이다. 하지만 p.foo()는 Person을 상속받았고 상속받은 객체는 상속의 멤버함수를 사용할 수 있다. public 일 경우에는 그렇다면 이럴 경우에는 Person이 출력되는지 job이 출력되는지 헷갈릴 수 있다.

  • 이와 같은 경우에는 항상 객체를 우선적으로 실행하게 된다. 무슨 말이냐면 p는 Teacher 객체이다. 그러므로 Teacher의 foo 함수가 실행될 것이다. 그리고 t는 Teacher의 객체이므로 Teacher의 foo 가 실행되게 된다.
  • 만일 Teacher::foo 에서 Person::foo 를 실행시키고 싶다면 범위확인연산자( :: ) 를 사용하면 된다. → Person::foo()

 

 

상속 살펴보기


상속을 받았는데 상속한 클래스에 접근 하고 싶을 때에 방법이 있다.

  1. 상속 객체의 멤버변수를 public으로 바꾸는 방법

  2. 멤버 변수가 private 로 선언 된 클래스에 접근하기 위해서는 상속해준 클래스의 멤버 함수를 이용한다. 추천 

     #include <iostream>
     using namespace std;
    
     class Person {
         int m_age;
     public:
         void setAge(int age) {
             m_age = age;
         }
         void Show() { cout << "age " << m_age << endl; }
     };
    
     class Teacher : public Person {
         int m_salary;
     public:
         void setD(int sal)
         {
             m_salary = sal;
         }
         void setAge(int age)
         {
             Person::setAge(age); // Person의 멤버함수를 호출한다.
         }
    
         void Show() {
             Person::Show();
         }
     };
    
     int main() {
         Teacher t;
    
         t.setAge(10);
         t.Show();
    
        return 0;
    }
    

'프로그래밍 언어 > C++' 카테고리의 다른 글

[따라배우는 C++] 상속의 기본(2)  (0) 2020.10.29

+ Recent posts