Back-end/C++

22. 04. 01 - 몬스터 전투 실습 ( 상속, 오버 라이딩, 가상 함수, 추상 클래스)

giggs 2022. 4. 10. 21:23

 

배운 내용 총 실습 : 몬스터 전투 

  1. 클래스 만들기
  2. 오버 로딩을 통한 다형성 구현하기
  3. 파일 분할하기 - 선언부와 구현부 + 파일 분할 후 몬스터 슬라임 추가해보기
  4. 상속의 구조로 변경 하기 
  5. 오버라이딩을 통한 다형성 구현하기
  6. 가상 함수, 순수 가상 함수

 

이번 시간에는

  1. -
  2. -
  3. -
  4. 상속의 구조로 변경 하기 
  5. 오버 라이딩을 통한 다형성 구현하기
  6. 가상 함수, 순수 가상함수, 추상 클래스

 

 


 

 

몬스터 상속처리 

 

 

  • 몬스터 각각 만들고 싸우게 하니까
  • 새로운 몬스터 생길 때마다 각각 부분에 처리해줘야 한다.
  • 몬스터 200개 있는데 1개 새로 추가되면.... 200개 부분에 다 추가 필요
  • 상속을 생각해볼 필요가 있다.

 

 

 

상속 시작

 

 

공통된 부분을 빼낼 것인데 - 아우룰 수 있는 단어 먼저 선택 - Monster

 

 

 

1. Monster . h 파일 만들어서 공통된 부분 빼낸다!

2. Attack( ) 함수 매개 변수 - 부모의 데이터 타입으로 받도록  수정

 

 

Monster . h

 

 

 


 

 

 

2. Monster . cpp 파일 만들어서 공통된 부분 빼낸다! + Attack( ) 구현

 

Monster . cpp

 

 

 


 

 

 

3. 자식 클래스 부분 

  • 상속받는 클래스로 해주고 
  • . h 파일 - 부모에게 올린 거 삭제해주고 - 생성자 수정
  • 자신만의 특징은 그대로 놔두기

 

Dragon . h

 

 

 


 

 

 

4. .cpp 파일에 부모에게 올린 구현부 지워주기, 특징 구현한 부분은 놔두기.

 

 

5. Ogre와 Slaim도 똑같이 해주면 완료!

 

 

 

 

" 상속 처리 끝 "

 

 

 

 


 

 

 

다형성 : 오버 라이딩 

 

 

 

다형성을 구현하는 도구 

  • 오버 로딩 / 오버라이드
  • 동일한 함수명을 가지고 다르게 작동하게 하는 것이 – 다형성 - 오버로딩

 

 

 

 

 

  • 우리가 한건 오버로딩 – 같은 함수명 다른 반응 

 

 

 

 

이번 시간에 해볼 것은 오버 라이딩을 통한 다형성 

  1. 몬스터 특수 능력 부여 : 슬라임에게 물리 방어력 능력 부여
  2. 자식 클래스마다 가지고 있는 GetDamage( ) 함수를 오버 라이딩
  3. 오버 라이딩 효과를 얻기 위해 가상 함수로 만들어줘야 한다.

 

 

 

 


 

 

1. 몬스터 특수 능력 부여 : 슬라임에게 물리 방어력 능력 부여

 

 

 

Slaim . h

 

 

## Check

  • Slaim의 멤버 변수 추가
  • 생성자 추가
  • Get( ) 함수 

 

 


 

 

 

2. 자식 클래스마다 가지고 있는 GetDamage( ) 함수를 오버 라이딩

 

 

2-1 : Attack ( ) 함수 수정 - 책임 전가

 

 

 

현재 Attack ( ) 함수를 보면

  • 때린 놈이 ( Monster ) 
  • 맞은 애( ref )한테 _healtg값 내놔 _Defense 내놔하고
  • 너( ref )의 _health 값 다시 세팅해 ( ref . SetHealth ) 이러고 있는 모습이다.

 

맞았을 때의 변화는 데미지 입었을 때 변화는- 맞은 놈이 더 잘 안다..

맞은 놈에게 책임을 넘겨버린다. -

맞은 놈이 데미지 변화 적용하도록 변경

 

 

 

Monster.h - Monster 클래스에 GetDamage( ) 만들어 주고

 

Monster . h

 

 

 

 

Monster . cpp - 기존의 Attack( ) 코드 수정

 

Monster . cpp

 

 

 

 

" 2-1번 책임 전가 끝 "

 

 

 


 

 

 

 

2-2 슬라임만의 Get Damage( ) 함수 구현

 

  • Monster에 있는 내용은 공통적인 내용들이 있다 - 누구나 가지고 있는 것
  • 그런데 슬라임에는 물리 공격 저항력이 있다.
  • 슬라임만의 GetDamage 재정의 안 해주면 -공통적인 내용으로 적용된다.
  • Attact( ) 공격받았을 때 GetDamage( ) 처리 시
  • Monster의 GetDamage( ) 적용

 

 

Slaim . h

 

 

 

슬라임 GetDamage ( ) 함수에

부모인 Monster 클래스 멤버 변수 사용하려면

  • 부모 클래스에서 - 멤버 변수 접근 제어자 protected로 변경 해주는 방법 1
  • 부모클래스 멤버 변수들 get( ) / set( )으로 접근해서 해주는 방법 2

 

 

 

" 2-2번 슬라임 GetDamage( ) 재정의 끝 "

 

 

 


 

 

2-3 재정의한 Slaim 클래스의 Damage( ) 메인에서 출력 테스트

 

 

드래곤 / 오거 / 슬라임 객체를 만들고

슬라임이 공격을 받게 되는 상황을 만들어 준다.

 

 

main . cpp

 

슬라임 객체가 공격받는 상황인데도

부모 클래스의 Monster GetDamage() 가 호출된다.

 

 

why?

 

 

 

Attack( ) 함수가 = 일반함수라서!

 

 

Monster . cpp

 

 

 

인자 값으로 Slaim이 들어왔지만.. 

Attack 함수가 일반 함수라서 담는 그릇인 Monster GetDamage( ) 함수 호출

 

 

 

 


 

 

 

 

들어오는 데이터 타입에 맞춰서 다르게 반응하게 해 주려면

가상 함수로 만들어 준다!

 

 

 

Monster . h

 

 

 

 

 

이처럼 무엇이 들어오냐에 따라 다르게 적용되는 것이 다형성

 

 

 

" 오버 라이딩을 이용한 다형성 확인 "

 

 

 


 

+@ 순수 가상 함수

 

 

  1. 새로운 Monster 생성  - Golem
  2. Golem은 마법공격 저항력을 가지고있다. 
  3. 마법공격저항력 테스트 위해

 

Monster 클래스에 MagicAttack( )과  GetMagicDamage( ) 추가해주기

  • Monster . h ---> MagicAttack( ) 함수와 GetMagicDamage( ) 선언
  • Monster . cpp ---> MagicAttack( )함수 GetMagicDamage( ) 구현 

 

 

Monster . h - 함수 구현도 같이 해줬다. ㅎㅎ

 

 

Monster . cpp

 

 

아직 자식 클래스에는 GetMagicDamage( )는 구현 안 한 상태 -----

 

 

 

 


 

 

 

main에서 MagicAttack 테스트

 

 

 

 

main . cpp

 

 

 

실행은된다. 다만 골램클래스에 마법 저항력 내용 구현 안 해준 상태다.

논리적인 오류 상황이다 - 나중에 발견됨 - 더 심각하다.

이렇게 깜빡하고 구현안 할 것을 대비하는 방법

 

 

 

 

함수를 - 순수 가상 함수로 만들어준다

  • Monster . h ---> GetMagicDamage( ) 선언부 뒤에 " = 0 " 을 붙여 순수 가상함수로 만들어준다.
  • Monster . cpp ---> GetMagicDamage( ) 구현부를 없애준다.

 

 

 

 

Monster . h

 

 

상속받는 애들은 반드시 이 함수를 구현해야 한다..

 

 

 

 

 

 

" 순수 가상 함수 완료 "

 

 

 

 

 


 

 

 

추상 클래스

 

  • 순수 가상 함수를 하나라도 보유하고 있는 클래스를 – 추상 클래스라고 한다!
  • 추상 클래스는 자신의 객체를 만들 수 없다. 
  • Monster a; 안된다는 뜻

 

 

추상 클래스는 자신의 객체를 만들 수 없다.

 

 

대신에 자식 클래스들에게 순수가상 함수 반드시 구현하도록 강제할 수 있다.

가상함수 만들어 줘서 추상 클래스가 된 Monster를 - 상속받은 자식 클래스들에게 에러남

 

 

 

추상 클래스를 상속받은 자식 클래스는 - 부모 클래스의 순수 가상 함수를 구현해야한다.

 

 

 

순수 가상 함수 구현 안 했다고 오류 났다..

해결하기 위해서는 각 자식 클래스에 GetDamage( ) 함수 구현해줘야 한다. 

 

 

 

 


 

 

## check point 

 

 

virtual GetDamage( ) 함수는 순수 가상 함수가 아니다. 

  • 슬라임만의 특별한 능력에 따라 슬라임만 재정의 해준 것
  • 슬라임이 물리 공격을 받을 경우 - 슬라임만의 GetDamage( )로 호출

 

 

virtual GetMagicDamage( ) = 0 ; 함수는 순수 가상 함수이다.

  • 순수 가상 함수가 된 GetMagicDamage( ) 함수는
  • 특별한 능력을 가지고 있는 골렘뿐 아니라 모든 자식 클래스에서 구현해야 한다.
  • 골램이 마법 공격을 받을 경우 - 골램만의 GetMagicDamage( )로 호출
  • 그런데 모든 자식 클래스에서 부모의 GetMagicDamage( ) 재정의 해 놓았다.
  • 따라서 - 특별한 능력이 없는 모든 자식 클래스별 GetMagicDamage( )로 호출
  • 다만 - 골렘을 제외한 다른 자식 클래스들은 마법 저항력 없으므로 일반 Attack( ) 시와 동일한 결과

 

 

 

main . cpp

 

 

 

 

개발자들의 실수 방지 ( 협업시에도 알려줄 수 있다. + Monster라는 객체는 필요 없다.클래스만 필요할 뿐 )

 

 

자식들이 반드시 만들어야 하는 함수를 순수 가상 함수로 해준다.

 

 

 

 

 


 

 

 



review



두 번째 복습 시간!

상속, 오버 라이딩, 가상 함수

상속의 구조로 변경해주고, 
자식만의 특수 능력을 재정의해주고,
자식의 데이터 타입으로 들어올 때는
들어온 타입에 맞게 호출되도록
가상 함수로 변경해주고 
복습하는 과정들이
매끄러웠고 이해하기 좋았다.


추가적인 내용은
virtual 함수 뒤에 = 0 으로
순수 가상 함수를 만들어주는 내용

순수가상함수를 가진 클래스는
추상 클래스가 되는 점

추상 클래스는 자신의 객체를 만들 수는 없지만
자식 클래스들에게 함수 구현을 강제할 수 있다!

순수 가상 함수 - 추상 클래스 내용을 보면서
java에서 abstrack class 해줬던 내용과
@override 해줬던 내용이 생각났다ㅎㅎ

= 0;을 해주는 C++과는 다르게 이 부분이 없어도
개념은 순수 가상 함수로 처리되었던 것이구나!