#include <iostream>
using namespace std;
class Player
{
public:
void Attack()
{
cout << "플레이어가 공격합니다. 공격력 = " << _damage << endl;
}
void Die()
{
_hp = 0;
cout << "플레이어가 죽었습니다. HP = " << _hp << endl;
}
public:
int _hp = 100;
int _damage = 30;
int _defence = 10;
};
class Knight : public Player // Player 클래스를 상속 받음.
{
// Player 클래스와 동일한 상태.
};
int main()
{
Knight knight; // Knight 클래스의 객체인 knight 선언.
knight.Attack(); // Knight의 멤버 함수 Attack() 호출.
knight.Die(); // Knight의 멤버 함수 Die() 호출.
return 0;
}
ex1) Knight is Player?
ex2) Player is Inventory?
ex3) Player has Inventory?
#include <iostream>
using namespace std;
class Player
{
public: // Class 외부에서 사용 가능.
void Attack()
{
cout << "플레이어가 공격합니다. 공격력 = " << _damage << endl;
}
void GetHit()
{
_hp -= 100;
cout << "플레이어가 피격 당했습니다! 남은 HP = " << _hp << endl;
if (_hp <= 0)
{
_hp = 0;
Die();
}
}
private: // 자기 자신과 자식 클래스에서 사용 가능.
void Die()
{
_hp = 0;
cout << "플레이어가 죽었습니다." << endl;
}
protected: // Class 내부에서만 사용.
int _hp = 100;
int _damage = 30;
int _defence = 10;
};
class Knight : public Player
{
public: // Class 외부에서 사용 가능.
Knight() // 기본 생성자.
{
cout << "Knight 생성!" << endl;
SetDamage();
}
private: // Class 내부에서만 사용 가능.
void SetDamage()
{
cout << "Knight의 공격력을 50으로 설정합니다!" << endl;
_damage = 50;
}
};
int main()
{
Knight knight;
knight.Attack();
//knight.Die(); // Die() 함수는 protected 이기 때문에 외부에서 사용 불가능.
//knight._hp = 10000; // _hp 변수는 private 이기 때문에 외부에서 사용 불가능.
//knight.SetDamage = 99999; // SetDamage() 함수는 pricate 이기 떄문에 외부에서 사용 불가능.
knight.GetHit();
return 0;
}
[오버로딩 vs 오버라이딩]
- 오버로딩 (Overloading) = 동일한 이름의 함수들을 매개 변수의 자료형이나 개수를 다르게 하여 같이 사용할 수 있게 하는 것.
- 오버라이딩 (Overriding) = 부모 클래스의 멤버 함수를 자식 클래스에서 재정의하여 사용하는 것.
! 오버로딩과 오버라이딩은 다른 개념이니까 헷갈리지 말자!
#include <iostream>
using namespace std;
class Player
{
public:
void Move() { cout << "Move Player !" << endl; } // Player 객체를 위한 Move() 함수.
public:
int _hp;
};
class Knight : public Player
{
public:
void Move() { cout << "Move Knight !" << endl; } // Knight 객체를 위한 Move() 함수.
public:
int _stamina;
};
void MovePlayer(Player* player) // 정적 바인딩 사용.
{
player->Move(); // Player의 Move() 함수가 호출되도록 정적 바인딩 됨.
}
void MoveKnight(Knight* knight) // 정적 바인딩 사용.
{
knight->Move(); // Knight의 Move() 함수가 호출되도록 정적 바인딩 됨.
}
int main()
{
Player p;
Knight k;
MovePlayer(&p);
MoveKnight(&k);
return 0;
}
#include <iostream>
using namespace std;
class Player
{
public:
virtual void Move() { cout << "Move Player !" << endl; }
// 멤버 함수 앞에 "virtual"을 사용하여, 가상 함수로 선언.
// 부모 클래스에서 가상 함수로 선언시, 자식 클래스에서 "virtual" 없어도 가상 함수로 선언됨.
// 한번 가상 함수 = 영원한 가상 함수.
public:
int _hp;
};
class Knight : public Player
{
public:
virtual void Move() override { cout << "Move Knight !" << endl; }
// 부모 클래스인 Player에서 가상 함수로 선언했으므로, "virtual" 없어도 알아서 가상 함수로 선언됨.
// 가상 함수라면, 명시적으로 가상 함수임을 나타내는 "virtual"을 붙여주는 것이 좋음.
// 자식 클래스에서는 부모 클래스에서 가상 함수에 "virtual"을 빼먹었는지 확인해주는 "override" 사용.
public:
int _stamina;
};
void MovePlayer(Player* player) // 동적 바인딩 사용.
{
player->Move(); // 함수를 호출한 실제 객체의 Move() 함수가 호출됨.
}
int main()
{
Player p;
Knight k;
MovePlayer(&p);
MovePlayer(&k);
return 0;
}
참고
- vftable을 만드는 곳 = 생성자의 선처리 부분.
#include <iostream>
using namespace std;
class Player
{
public:
virtual void Attack() = 0;
// 순수 가상 함수 선언. (함수 뒤에 "= 0" 을 붙여줌.)
// Player 클래스 = 추상 클래스가 됨.
public:
int _hp;
};
class Knight : public Player
{
public:
virtual void Attack()
{
cout << "Knight Attack!" << endl;
}
public:
int _stamina;
};
int main()
{
//Player p; // Player = 추상 클래스 이므로 직접 객체 생성 불가능.
Knight k; // Knight = 부모 클래스 Player의 순수 가상 함수 Attack()을 재정의 했으므로 객체 생성 가능.
k.Attack(); // 객체 k의 Attack() 함수 호출.
return 0;
}
#include <iostream>
using namespace std;
class Player // 부모 클래스 Player
{
public:
Player() { cout << "Monster()" << endl; }; // Player 생성자
~Player() { cout << "~Monster()" << endl; }; // Player 소멸자
public:
};
class Pet // Knight의 멤버 클래스 Pet
{
public:
public:
int _hp = 100;
};
class Knight : public Player // 자식 클래스 Knight
{
public:
Knight() { cout << "Knight()" << endl; _pet = new Pet(); } // Knight 생성자
~Knight() { cout << "~Knight()" << endl; delete _pet; } // Knight 소멸자
public:
Pet* _pet;
};
int main()
{
Player* player = new Knight; // Knight 객체를 Player 타입으로 사용
delete player; // player 소멸 (실제 객체 = Knight)
return 0;
}
#include <iostream>
using namespace std;
class Player // 부모 클래스 Player
{
public:
Player() { cout << "Monster()" << endl; }; // Player 생성자
virtual ~Player() { cout << "~Monster()" << endl; }; // Player 소멸자 (동적 바인딩)
public:
};
class Pet // Knight의 멤버 클래스 Pet
{
public:
public:
int _hp = 100;
};
class Knight : public Player // 자식 클래스 Knight
{
public:
Knight() { cout << "Knight()" << endl; _pet = new Pet(); } // Knight 생성자
~Knight() { cout << "~Knight()" << endl; delete _pet; } // Knight 소멸자
public:
Pet* _pet;
};
int main()
{
Player* player = new Knight; // Knight 객체를 Player 타입으로 사용
delete player; // player 소멸 (실제 객체 = Knight)
return 0;
}