class ClapTrap
{
private:
std::string _name;
unsigned int _hitPoints;
unsigned int _energyPoints;
unsigned int _attackDamage;
public:
ClapTrap();
ClapTrap(std::string name);
ClapTrap(const ClapTrap &obj);
ClapTrap &operator=(const ClapTrap &obj);
~ClapTrap();
void attack(const std::string &target);
void takeDamage(unsigned int amount);
void beRepaired(unsigned int amount);
};
//ClapTrap.hpp
private:
std::string _name;
unsigned int _hitPoints;
unsigned int _energyPoints;
unsigned int _attackDamage;
//ClapTrap.hpp
protected:
std::string _name;
unsigned int _hitPoints;
unsigned int _energyPoints;
unsigned int _attackDamage;
ClapTrap 클래스 상속
class ScavTrap : public ClapTrap
{
public:
ScavTrap();
ScavTrap(std::string name);
ScavTrap(const ScavTrap &obj);
ScavTrap &operator=(const ScavTrap &obj);
~ScavTrap();
void attack(const std::string &target);
void guardGate();
};
공통 기능을 부모 클래스에 구현해서 상속하고 특화된 기능을 자식 클래스에 추가
추가 함수
guardGate(): Gate keeper 모드 활성화 메시지 출력
attack() 함수는 다른 메시지를 출력하도록 오버라이딩 -> 같은 attack() 메서드라도 각 클래스에서 다르게 동작함
void ClapTrap::attack(const std::string &target)
{
if (_hitPoints == 0)
{
std::cout << "ClapTrap " << _name << " has already died" << std::endl;
}
else if (_energyPoints == 0)
{
std::cout << "ClapTrap " << _name << " has no energy to attack!" << std::endl;
}
else
{
std::cout << "ClapTrap " << _name << " attacks " << target << ", causing " << _attackDamage << " points of damage!" << std::endl;
_energyPoints--;
}
}
void ScavTrap::attack(const std::string &target)
{
if (_hitPoints == 0)
{
std::cout << "ScavTrap " << _name << " has already died." << std::endl;
}
else if (_energyPoints == 0)
{
std::cout << "ScavTrap " << _name << " has no energy to attack!" << std::endl;
}
else
{
std::cout << "ScavTrap " << _name << " attacks " << target << ", causing " << _attackDamage << " points of damage!" << std::endl;
_energyPoints--;
}
}
ClapTrap 클래스 상속
class FragTrap : public ClapTrap
{
public:
FragTrap();
FragTrap(std::string name);
FragTrap(const FragTrap &obj);
FragTrap &operator=(const FragTrap &other);
~FragTrap();
void highFivesGuys();
};
추가 함수
highFivesGuys(): positive high fives 요청 메시지 출력
void FragTrap::highFivesGuys()
{
if (_hitPoints == 0)
{
std::cout << "FragTrap " << _name << " has already died" << std::endl;
}
else if (_energyPoints == 0)
{
std::cout << "FragTrap " << _name << " has no energy to high-five!" << std::endl;
}
else
{
_energyPoints--;
std::cout << "FragTrap " << _name << " says : make some high-five!" << std::endl;
}
}
int main() {
ClapTrap clapTrap("apple");
ScavTrap ScavTrap("pineapple");
FragTrap FragTrap("Flume");
std::cout << std::endl;
clapTrap.attack("banana");
clapTrap.takeDamage(3);
clapTrap.beRepaired(2);
clapTrap.takeDamage(9);
std::cout << std::endl;
ScavTrap.attack("banana");
ScavTrap.guardGate();
ScavTrap.attack("banana");
ScavTrap.takeDamage(100);
ScavTrap.beRepaired(2);
std::cout << std::endl;
FragTrap.attack("banana");
FragTrap.highFivesGuys();
FragTrap.takeDamage(100);
FragTrap.beRepaired(2);
std::cout << std::endl;
return 0;
}
ClapTrap apple is born! // ClapTrap 객체 생성
ScavTrap pineapple is born! // ScavTrap 객체 생성
FragTrap Flume is born! // FragTrap 객체 생성
ClapTrap apple attacks banana, causing 0 points of damage! // 공격력 0으로 공격
apple is taking 3 damage. // 3 데미지를 입음 (HP: 10→7)
ClapTrap apple is repaired 2 hit points. Remaining hit points: 9 // 체력 회복 (HP: 7→9)
ClapTrap apple has died. // 9 데미지를 더 입어 사망 (HP: 9→0)
ScavTrap pineapple attacks banana, causing 20 points of damage! // 공격력 20으로 공격
ScavTrap pineapple has entered Gate keeper mode. // 고유 기능 사용
ScavTrap pineapple attacks banana, causing 20 points of damage! // 다시 공격
ScavTrap pineapple has died. // 100 데미지를 입어 사망 (HP: 100→0)
ScavTrap pineapple has already died. // 사망 상태에서 회복 시도 실패
FragTrap Flume attacks banana, causing 30 points of damage! // 공격력 30으로 공격
FragTrap Flume says : make some high-five! // 고유 기능 사용
FragTrap Flume has died. // 100 데미지를 입어 사망 (HP: 100→0)
FragTrap Flume has already died. // 사망 상태에서 회복 시도 실패
FragTrap Flume is destroyed! // 소멸자 호출 (역순)
ScavTrap pineapple is destroyed! // 소멸자 호출
ClapTrap apple is destroyed! // 소멸자 호출
생성자 동작 순서
부모 클래스 생성자 -> 자식 클래스 생성자
소멸자 동작 순서
자식 클래스 소멸자 -> 부모 클래스 소멸자
초기화 리스트를 이용해 명시적으로 호출
ScavTrap::ScavTrap(std::string name) : ClapTrap(name) {
_name = name;
_hitPoints = 100;
_energyPoints = 50;
_attackDamage = 20;
std::cout << "ScavTrap " << _name << " is born!" << std::endl;
}
따라서, 부모 클래스의 생성자가 private인 경우 자식 클래스에서 해당 생성자를 호출하는 것은 불가능하다. 생성자는 외부에서 직접 호출되지 않고 객체를 생성할 때 자동으로 호출되기 때문이다. 상속 받더라도 private 생성자는 자식 클래스에서 사용할 수 없다.