본문 바로가기
  • 쓸쓸한 개발자의 공부방
C++

[C++] 상속 (Inheritance), protected

by 심찬 2021. 8. 25.

 

 

상속(INHERITANCE)

 

 - 한 클래스가 다른 클래스에서 정의된 속성들 (데이타, 함수) 를 이어 받아서 사용하는 것!

 - 이미 정의된 클래스를 기반으로 새로운 클래스를 설계

 - 소프트웨어 재사용성을 지원

 

장점

 - 코드 중복을 막는다

 - 상속을 통해서 기존 클래스에 새로운 특징을 추가한 새로운 타입의 설계

 - 다형성을 활용한 객체지향 디자인 기법

 

상속의 기본 개념

 

교수님과 학생 클래스가 아래와 같이 있다. 두 클래스는 이름과 나이의 공통 속성이 있다.

 

#include <iostream>
#include <string>

class Professor
{
    std::string name;
    int age;
    int major;    
};

class Student
{
    std::string name;
    int age;
    int id;
};

int main()
{
    
}

공통된 특성을 모아서 Person 클래스를 설계한다.

교수님, 학생은 Person으로 부터 상속 받는다.

Student는 사실 id 만보이지만 Person의 name과 age를 갖고 있다.

ParttimeStudent와 같은 새로운 class는 student를 상속 받고, salary만 추가로 생성되었다. Person의 속성, Student 의 속성을 모두 갖는다.

#include <iostream>
#include <string>

class Person
{
    std::string name;
    int age;
};

class Professor : public Person
{
    int major;    
};

class Student : public Person
{
    int id;
};

class ParttimeStudent : public Student
{
    int salary;
};

int main()
{
    Professor p;
    Student   s;
}

 

<클래스 상속 구조>

 


객체지향 언어별 상속 문법 표기법

 

객체지향 언어들 마다 상속을 위한 문법이 조금씩 다르다.

C++ class Student : public Person
C# class Student : Person
Java class Student extends Person

 


protected

 

변수 a에 대한 접근은 아무리 파생 클래스라고 하더라도 private이기 때문에 접근이 불가하다.

private는 자신의 클래스에서만 접근이 가능, 파생 클래스 및 외부에서는 접근 불가

그래서 protected 라는 접근 지정자로 정의된 변수 b 에는 파생 클래스에서도 접근이 가능하다.

protected는 파생 클래스에서도 접근이 가능

class Base
{
private:   int a;
protected: int b;
public:    int c;
};

class Derived : public Base
{
public:
    void foo()
    {
        a = 10; // error
        b = 10; // ok
        c = 10; // ok 
    }
};

int main()
{
    Derived derv;
    derv.a = 10; // error
    derv.b = 10; // error
    derv.c = 10; // ok
}

 

main.cpp:13:9: error: ‘int Base::a’ is private within this context

main.cpp:22:10: error: ‘int Base::a’ is private within this context

main.cpp:23:10: error: ‘int Base::b’ is protected within this context

 

 

  private protected public
동일 클래스(same class) O O O
파생 클래스(derived class) X O O
others X X O

 

private VS protected

 

아래와 같이 Person 클래스가 있고 Student 는 Person을 상속받았다.

Student 클래스에서 print() 는 name, age, id를 출력하려고 하는데 아래와 같은 에러가 발생한다.

왜냐하면 Person에 접근 지정자를 넣지 않아서 모든 멤버가 private 접근 지정자로 설정되기 때문이다.

#include <iostream>
#include <string>

class Person
{
    std::string name;
    int age;
    int getAge() const { return age;}
};

class Student : public Person
{
    int id;
public:
    void print() const
    {
        std::cout << name << std::endl;
        std::cout << age  << std::endl;
        std::cout << id   << std::endl;
    }
};

int main()
{
    Student student;
    
}

 

main.cpp:17:22: error: ‘std::string Person::name’ is private within this context

main.cpp:18:22: error: ‘int Person::age’ is private within this context

 

1) person의 age를 접근하기 위해  public 접근지정자로 getAge()를 만들어 주는 방법이 있다. (권장하는 방법)

2) name, age를 protected 접근 지정자로 해주면 파생 클래스에서 접근이 가능해진다. 직접 접근이 가능해지기 때문에 안정성 측면에서는 그닥 좋지 않은 방법이다.

#include <iostream>
#include <string>

class Person
{
protected:
    std::string name;
    int age;
public:
    int getAge() const { return age;}
    Person(){};
    Person(const std::string& str, int age) : name(str), age(age){};
};

class Student : public Person
{
    int id;
public:
    Student(){};
    Student(const std::string& str, int age, int id) : Person(str,age), id(id){};
    void print() const
    {
        std::cout << name << std::endl;
        std::cout << age  << std::endl;
        std::cout << id   << std::endl;
    }
};

int main()
{
    Student student;
    student.print();
    
    Student student1("Kim", 22, 101);
    student1.print();
}

객체를 생성해서 print 결과를 보여주고 있다. 

생성자를 참조 변수로 받아서 처리하고 있고, 초기화를 하는데 Person을 부르도록 했다. id는 student만 가지고 있기에 id(id) 를 통해 값을 넣어준다. (this없이도 잘된다.)

 

 

 

댓글