준비하는 대학생

[Cpp] 클래스 관계 - 상속 본문

Programming/C++

[Cpp] 클래스 관계 - 상속

Bangii 2023. 3. 6. 18:52

객체 지향 프로그래밍은 하나의 클래스를 단독으로 사용하지 않는다. 

각 클래스 간 관계가 존재하고 이를 분류하면 아래와 같다.

 

클래스 관계
상속(Inheritance)
is - a
연관(Association)
is related to
종속 (Dependency)
uese - a
  소유(Aggregation)
has - a
구성(Composition)  

 

클래스 간 관계는 주로 UML을 이용하여 설명한다. 

UML에서는 상속하는 클래스에서 상속받는 클래스로 화살표로 나타낸다. 

예를 들어 강아지 클래스는 더 큰 범주인 동물 클래스를 상속받는다고 가정하면 아래 그림과 같이 나타낼 수 있다.

cpp에서는 위의 그림처럼 상속하는 클래스 즉 범용적인 클래스를 베이스클래스 또는 슈퍼 클래스라고 부르고, 구체적인 클래스를 파생클래스 또는 서브 클래스라고 부릅니다. 위 그림에서 보면 Dog는 파생클래스이고, Animal은 베이스 클래스가 되는 것을 알 수 있다. 

 

일반적으로 구체적인 파생클래스는 범용적인 베이스 클래스보다 더 많은 특징을 갖고 있다. 

예를 들면 강아지는 동물의 특징 외에도 다른 특징들이 존재한다. 이처럼 파생클래스는 베이스 클래스의 특징을 갖고 더 많은 특징을 추가하기 때문에 베이스클래스를 확장한 것 이라고 표현한다.

 

파생클래스는 베이스클래스의 모든 데이터 변수, 멤버변수를 가진 상태에서 추가 데이터 멤버와 멤버함수를 갖는다. 

(다만 이때 생성자, 소멸자, 할당연산자는 상속받지 못한다.)

상속의 종류에는 public, protected, private의 3가지 가 있다. 하지만 실질적으로는 public을 제외한 나머지 상속을 잘 사용하지 않는다.

Cpp에서 상속을 받는 방법은 클래스 이름 뒤에 콜론(:)을 입력하고 접근제한자 (public, protected, private)와 베이스 클래스를 입력하여 만든다. 

Animal 클래스를 상속받는 Dog 클래스를 cpp에서 작성하면 아래와 같다.

class Dog : public Animal{
// 클래스 내용
}

 

파생클래스는 베이스클래스의 모든 데이터 변수, 멤버변수를 갖는다고 앞서 설명했다. 

하지만 파생클래스는 베이스 클래스에서 private로 선언된 데이터 멤버 변수에는 접근할 수 없다.

그러므로 이에 접근하기 위해서는 직접 접근하는 것이 아니라 getter/setter 와 같은 함수를 만들어 값을 간접적으로 접근할 수 있다. 

 

void Person::setId(long id)
{
  identity = id; 
  assert(identity >= 100000000 && identity <= 999999999) ; 
}

void Student::setId(long id, double gp){
    cout<<"오버라이딩된 setid"<<endl;
    Person::setId(id); //위임 delegation
    gpa = gp;
}

 

위 코드는 Student가 Person의 클래스를 상속받은 상태에서 Student에서 setId를 만드는 상황이다.

아 때 파생클래스에서 setId를 오버라이딩했을 때 상속받은 id는 private 변수이므로 직접 접근할 수 없으므로 public으로 생성된 Person::setId를 호출하여 id 멤버변수를 설정했다. 

이처럼 파생클래스에서 베이스클래스 함수를 호출해서 어떤 작업을 하게 만드는 것을 위임(delegation) 이라고 한다.

 

상속되지 않는 멤버

앞서 설명한 대로 파생클래스는 베이스 클래스로부터 생성자, 소멸자 , 할당연산자는 상속되지 않는다.

왜냐하면 대부분 생성자는 해당 클래스의 데이터변수를 초기화하는 경우가 일반적이다.

하지만, private로 선언된 데이터변수는 파생클래스가 직접접근할 수 없으므로 초기화가 불가능하다.

소멸자에서도 마찬가지로 접근을 할 수 없기 때문에 상속받을 수 없다. 

따라서 파생클래스에서 베이스클래스 생성자를 먼저 호출한 뒤에 파생클래스의 데이터 멤버를 초기화하는 방법으로 생성자를 사용할 수 있다.  소멸자도 생성자와 반대의 순서로 파생클래스에 데이터 멤버를 소멸한 뒤 베이스클래스의 소멸자를 호출하면 된다.

 

'Programming > C++' 카테고리의 다른 글

[Cpp] 다형성  (0) 2023.03.10
[Cpp] 클래스 관계 - 연관(association, aggregation, composition)  (0) 2023.03.08
Comments