모습은 같지만 형태는 다른 것
dynamic_cast
상속관계에 있는 두 포인터 간 캐스팅 지원
Base p;
Derived c;
Base* p_p = &p;
Derived* p_c = dyanmic_cast<Derived*>(p_p); // 오류!
자식 클래스에서 부모에게 상속받은 함수를 이름은 같지만 내용은 다른 함수로 재정의하는 것
virtual
함수virtual
로 지정하면 자식 클래스에서 해당 함수를 오버라이딩하고 이후에 업캐스팅된 경우에도 자식 클래스의 함수를 호출함Animal
클래스부모 클래스
std::string type
makeSound()
: 적절한 소리를 출력해야 함Dog
, Cat
클래스Animal
클래스 상속
type
: 자신의 클래스명으로 초기화WrongAnimal
, WrongCat
클래스WrongAnimal
의 makeSound()
에 virtual
키워드를 추가하지 않음WrongCat
의 makeSound()
를 호출해도 WrongAnimal
의 makeSound()
가 호출됨int main(void)
{
const Animal* meta = new Animal();
const Animal* i = new Cat();
const Animal* j = new Dog();
meta->makeSound();
i->makeSound();
j->makeSound();
delete j;
delete i;
delete meta;
std::cout << std::endl;
const WrongAnimal* wrong_meta = new WrongAnimal();
const WrongAnimal* k = new WrongCat();
wrong_meta->makeSound();
k->makeSound();
delete k;
delete wrong_meta;
return (0);
}
Brain
클래스std::string ideas[100]
Dog
, Cat
클래스Brain*
추가new Brain()
으로 생성delete
로 삭제Animal
배열을 만들고 채우기Dog
반은 Cat
Animal
삭제하기Animal *
에 할당!)Dog
와 Cat
의 복사는 얕으면 안 됨Brain*
을 복사할 때 깊은 복사를 해야 하므로 복사 생성자와 복사 대입 연산자 수정virtual void makeSound(void) const = 0;
= 0
를 붙이면 순수 가상 함수가 됨Animal
클래스의 객체를 만들 수 없도록 수정C++98에는 존재하지 않지만 순수 추상 클래스를 인터페이스라고 부름
AMateria
class AMateria
{
protected:
...
public:
AMateria(std::string const & type);
...
std::string const &getType() const; // Returns the materia type
virtual AMateria* clone() const = 0;
virtual void use(ICharacter& target);
};
Ice
, Cure
AMateria
상속type
은 소문자로 지정: ice
, cure
clone()
은 같은 타입을 리턴Ice
에 사용했으면 새로운 Ice
인스턴스를 리턴use(ICharacter&)
각각 아래의 내용을 출력 (<name>
은 인자로 전달된 캐릭터의 이름)
Ice
: * shoots an ice bolt at <name> *
Cure
: * heals <name>’s wounds *
Materia를 다른 것에 할당할 때,
type
을 복사하지 말 것
ICharacter
class ICharacter
{
public:
virtual ~ICharacter() {}
virtual std::string const &getName() const = 0;
virtual void equip(AMateria* m) = 0;
virtual void unequip(int idx) = 0;
virtual void use(int idx, ICharacter& target) = 0;
};
Character
ICharater
상속equip()
: Materia를 슬롯의 0~3번째 순서대로 장착use
, unequip
하려고 하는 경우 아무것도 하지 않음unequip()
: Materia 버리기 (Materia를 삭제하면 안 됨)unequip()
호출 전 주소를 저장해두거나 할 것use(int, ICharacter&)
: slot[idx]
의 AMateria::use()
에 target
을 넘겨줌캐릭터의 인벤토리는 모든 종류의
AMateria
를 지원해야 함
IMateriaSource
class IMateriaSource
{
public:
virtual ~IMateriaSource() {}
virtual void learnMateria(AMateria*) = 0;
virtual AMateria* createMateria(std::string const &type) = 0;
};
MateriaSource
IMateriaSource
상속learn
하고 필요할 때 create
하는 역할learnMateria(AMateria*)
clone()
할 수 있도록 메모리에 저장 createMateria(std::string const &)
learnMateria()
된 Materia와 인자로 전달된 type
이 동일하면 클론해서 리턴, type
을 알 수 없으면 0
리턴클래스 전방 선언
헤더 파일이 서로를 참조하는 경우 사용
class ICharacter; class AMateria { ... };
int main()
{
IMateriaSource* src = new MateriaSource();
src->learnMateria(new Ice());
src->learnMateria(new Cure());
ICharacter* me = new Character("me");
AMateria* tmp;
tmp = src->createMateria("ice");
me->equip(tmp);
tmp = src->createMateria("cure");
me->equip(tmp);
ICharacter* bob = new Character("bob");
me->use(0, *bob);
me->use(1, *bob);
delete bob;
delete me;
delete src;
return (0);
}