자식객체를 부모 타입에 집어넣는 행위 업캐스팅
과제 : 상속 구조를 그림으로 표현하여 코드로 옮겨본다.
======[ 다운캐스팅 ]=======================================================
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <string>
using namespace std;
// 중복코드를 가지고 만든 캐릭터 클래스
class Character {
protected:
// 중복 속성들
string _name;
int _hp;
int _damage;
public:
Character(string name, int damage) {
_name = name;
_hp = 100;
_damage = damage;
}
// 중복 메소드들
void Move() {
cout << "[" << _name << "] 님이 이동을 합니다. " << endl;
}
void Hit(int damage) {
cout << "[" << _name << "] 님이 " << damage << " 데미지를 입었습니다. " << endl;
}
void Die() {
cout << "[" << _name << "] 님이 사망했습니다. " << endl;
}
void Attack() {
cout << "[" << _name << "] 님이 " << _damage << "만큼의 공격을 합니다. " << endl;
}
};
// 플레이어는 캐릭터를 상속함
class Player : public Character
{
private:
int _level;
int _gravity;
string _talkMessage;
public:
Player(string name, string talkMessage, int damage)
// 플레이어의 생성자를 호출하기전에 캐릭터의 생성자를 호출함
: Character(name, damage) {
_talkMessage = talkMessage;
_level = 1;
_gravity = 1;
cout << "[" << _name << "] 님이 접속하였습니다." << endl;
Talk();
}
~Player() {}
void Talk() {
cout << "[" << _name << "] 메시지 : "
<< _talkMessage << endl;
}
void Jump() {
cout << "[" << _name << "] 님이 점프를했습니다. " << endl;
}
};
class Monster : public Character
{
private:
int _skillType;
public:
Monster(string name, int skillType, int damage)
: Character(name, damage) {
_skillType = skillType;
cout << "[" << _name << "] 님이 나타났습니다." << endl;
}
~Monster() {}
void Skill()
{
cout << "[" << _name << "] 님이 " << _skillType << "타입의 스킬을 사용합니다. " << endl;
}
};
class Creature : public Character
{
private:
int _time;
public:
Creature(string name, int time, int damage)
: Character(name, damage) {
_time = time;
cout << "[" << _name << "] 님이 소환 됐습니다." << endl;
Timer();
}
~Creature() {}
void Timer()
{
cout << "[" << _name << "] 님이 " << _time << " 시간뒤에 소멸됩니다." << endl;
}
};
//전투 스테이지로 각 캐릭터들은 이동, 타격 사망을 할 수 있다.
class WarStage{
public:
/*
void MoveTarget(Player* player){
player->Move();
}
void MoveTarget(Monster* monster){
monster->Move();
}
void MoveTarget(Creature* creature){
creature->Move();
}
*/
// 서로관의 관계를 단순화
void MoveTarget(Character* character){
character->Move();
}
};
//캐릭터들을 이동 시킴
//캐릭터들을 배열로 받아 반복문을 통해 Move 메소드를 실행한다.
void MoveAll(Character** characters){
for (int i = 0; i < 3; i++)
{
characters[i]->Move();
}
}
void main()
{
// 메모리 주소를 할당 NEW
Player* player = new Player("홍길동", "안녕", 100);
Monster* monster = new Monster("몬스터", 1, 100);
Creature* creature = new Creature("크리쳐", 10, 100);
WarStage* warStage = new WarStage();
/*
warStage->MoveTarget(player);
warStage->MoveTarget(monster);
warStage->MoveTarget(creature);
*/
// 메모리 주소로 접근
// 객체형 배열 생성
// 캐릭터 객체 배열에 자식 객체 대입
Character* characters[3];
characters[0] = player; // 업캐스팅(player* -> Character);
characters[1] = monster;// 업캐스팅(monster* -> Character);
characters[2] = creature;// 업캐스팅(creature* -> Character);
MoveAll(characters);
delete warStage;
delete player;
delete monster;
delete creature;
/*
// 캐스팅은 주소를 가지고 있으므로 매모리 주소로 접근 해야만 된다. (포인터)
// 업캐스팅은 상속 에서만 가능합
// 업캐스팅
Character* c = new Player("홍길동", "안냥", 100);
// 다운캐스팅 캐릭터 타입의 주소를 플레이어 타입의 주소로 변경 대입 자식의 타입으로 바꾸는것.
//플레이어 포인터 객체 p에 플레이어 주소를 대입한다.
Player* p = (Player*)c;
p->Jump();
delete p;
// 업캐스팅 ( 그리쳐객체의 주소를 캐릭터 포인터 변수에 대입)
Character* c = new Creature("멀록", 10, 100);
//c ->Timer() 에러발생
//다운캐스팅 ( 캐릭터 타입의 주소를 크리쳐 타입의 주소로 변경 대입
Creature* cr = (Creature*)c;
cr->Timer();
delete cr;
//c = new Car;
*/
}
====[ 가상함수 ]============================================================
// 부모 클래스형 배열을 만든다.
// 배열에 각 객체 변수를 대입한다.
// 배열 객체를 받아 반복문을 사용하여 각 객체의Move 메소드를 실행한다.
// 자료구조.
// 가상함수 - 진짜가 아닐수도 있다. 오버라이드 함수가 있을때 부모 클래스의 함수가 블라인드 된다.
virtual void Move() {
cout << "[" << _name << "] 님이 이동을 합니다. " << endl;
}
// 상속 구조에서 부모 클래스의 메소드를 오버라이드 할때 자식 클래스에서 재정의 하고 부모 클래스에서
메소드 명 앞에 virtual 을 붙여준다.
오버라이드 강제화. - 순수 가상 함수
// 모든 캐릭터 들이 Attack을 새로 만들어야 할 경우
// 부모 클래스의 Attack의 정의는 의미 없어짐.
// 가상함수는 자식 클래스의 재정의 ( 오버라이드) 에 대한 강제성이 없지만
// 순수 가상함수는 자식 클래스의 재정의( 오버라이드 )를 강제화함
// 하나 이상의 순수 가상 함수를 가진 클래스는 추상 클래스가 된다.
// 생성 할 경우 오류가 난다. 추상 클래스는 생성 할 수 없다.
virtual void Attack() = 0; // 부모 클래스에서 접근 하기 위해 순수 가상함수가 필요함.
http://www.unity2d.kr/index.php?mid=cpp_csharp_study&page=2&document_srl=302
======================================================================
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <string>
using namespace std;
// 중복코드를 가지고 만든 캐릭터 클래스
class Character {
protected:
// 중복 속성들
string _name;
int _hp;
int _damage;
public:
Character(string name, int damage) {
_name = name;
_hp = 100;
_damage = damage;
}
// 중복 메소드들
// 가상 함수
virtual void Move() {
cout << "[" << _name << "] 님이 이동을 합니다. " << endl;
}
void Hit(int damage) {
cout << "[" << _name << "] 님이 " << damage << " 데미지를 입었습니다. " << endl;
}
void Die() {
cout << "[" << _name << "] 님이 사망했습니다. " << endl;
}
// 모든 캐릭터 들이 Attack을 새로 만들어야 할 경우
// 부모 클래스의 Attack의 정의는 의미 없어짐.
// 가상함수는 자식 클래스의 재정의 ( 오버라이드) 에 대한 강제성이 없지만
// 순수 가상함수는 자식 클래스의 재정의( 오버라이드 )를 강제화함
// 하나 이상의 순수 가상 함수를 가진 클래스는 추상 클래스가 된다.
// 생성 할 경우 오류가 난다. 추상 클래스는 생성 할 수 없다.
virtual void Attack() = 0;
};
// 플레이어는 캐릭터를 상속함
class Player : public Character
{
private:
int _level;
int _gravity;
string _talkMessage;
public:
Player(string name, string talkMessage, int damage)
// 플레이어의 생성자를 호출하기전에 캐릭터의 생성자를 호출함
: Character(name, damage) {
_talkMessage = talkMessage;
_level = 1;
_gravity = 1;
cout << "[" << _name << "] 님이 접속하였습니다." << endl;
Talk();
}
~Player() {}
void Talk() {
cout << "[" << _name << "] 메시지 : "
<< _talkMessage << endl;
}
void Jump() {
cout << "[" << _name << "] 님이 점프를했습니다. " << endl;
}
void Attack() {
cout << "[" << _name << "] 님이 " << _damage << " 칼을 휘두르면서 공격을 합니다. " << endl;
}
};
class Monster : public Character
{
private:
int _skillType;
public:
Monster(string name, int skillType, int damage)
: Character(name, damage) {
_skillType = skillType;
cout << "[" << _name << "] 님이 나타났습니다." << endl;
}
~Monster() {}
void Skill()
{
cout << "[" << _name << "] 님이 " << _skillType << "타입의 스킬을 사용합니다. " << endl;
}
// 오버라이드
void Attack() {
cout << "[" << _name << "] 님이 " << _skillType << " 을 사용 하면서 공격을 합니다. " << endl;
}
};
class Creature : public Character
{
private:
int _time;
public:
Creature(string name, int time, int damage)
: Character(name, damage) {
_time = time;
cout << "[" << _name << "] 님이 소환 됐습니다." << endl;
Timer();
}
~Creature() {}
void Timer()
{
cout << "[" << _name << "] 님이 " << _time << " 시간뒤에 소멸됩니다." << endl;
}
// 가상 함수 선언
void Move() {
cout << "[" << _name << "] 팔짝 팔짝 뛰면서 님이 이동을 합니다. " << endl;
}
void Attack() {
cout << "[" << _name << "] 님이 하면서 공격을 합니다. " << endl;
}
};
//전투 스테이지로 각 캐릭터들은 이동, 타격 사망을 할 수 있다.
class WarStage{
public:
// 서로관의 관계를 단순화
void MoveTarget(Character* character){
character->Move();
}
};
//캐릭터들을 이동 시킴
//캐릭터들을 배열로 받아 반복문을 통해 Move 메소드를 실행한다.
void ActionAll(Character** characters){
for (int i = 0; i < 3; i++)
{
characters[i]->Move();
characters[i]->Attack();
}
}
void main()
{
//객체타입 변수 생성 / 생성자 호출 / 맴버변수 초기화
Player* player = new Player("오징어", "맛있엉", 1);
Monster* monster = new Monster("꼴뚜기", 1, 1);
Creature* creature = new Creature("갑오징어", 2, 1);
//객체 배열 생성 후 객체 변수 대입
Character* characters[3];
characters[0] = player;
characters[1] = monster;
characters[2] = creature;
// Mmove 함수 호출
ActionAll(characters);
for (int i = 0; i < 3; i++)
{
delete characters[i];
}
}
=====[UNITY 슈팅게임]=======================================================
댓글
댓글 쓰기