모습은 같지만 형태는 다른 것
dynamic_cast상속관계에 있는 두 포인터 간 캐스팅 지원
Base p;
Derived c;
Base* p_p = &p;
Derived* p_c = dyanmic_cast<Derived*>(p_p); // 오류!
자식 클래스에서 부모에게 상속받은 함수를 이름은 같지만 내용은 다른 함수로 재정의하는 것
virtual 함수virtual로 지정하면 자식 클래스에서 해당 함수를 오버라이딩하고 이후에 업캐스팅된 경우에도 자식 클래스의 함수를 호출함
Animal 클래스부모 클래스
std::string typemakeSound(): 적절한 소리를 출력해야 함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 반은 CatAnimal 삭제하기Animal *에 할당!)Dog와 Cat의 복사는 얕으면 안 됨Brain*을 복사할 때 깊은 복사를 해야 하므로 복사 생성자와 복사 대입 연산자 수정virtual void makeSound(void) const = 0;
= 0를 붙이면 순수 가상 함수가 됨Animal 클래스의 객체를 만들 수 없도록 수정C++98에는 존재하지 않지만 순수 추상 클래스를 인터페이스라고 부름
AMateriaclass 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, CureAMateria 상속type은 소문자로 지정: ice, cureclone()은 같은 타입을 리턴Ice에 사용했으면 새로운 Ice 인스턴스를 리턴use(ICharacter&)각각 아래의 내용을 출력 (<name>은 인자로 전달된 캐릭터의 이름)
Ice: * shoots an ice bolt at <name> *Cure: * heals <name>’s wounds *Materia를 다른 것에 할당할 때,
type을 복사하지 말 것
ICharacterclass 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;
};
CharacterICharater 상속equip(): Materia를 슬롯의 0~3번째 순서대로 장착use, unequip하려고 하는 경우 아무것도 하지 않음unequip(): Materia 버리기 (Materia를 삭제하면 안 됨)unequip() 호출 전 주소를 저장해두거나 할 것use(int, ICharacter&): slot[idx]의 AMateria::use()에 target을 넘겨줌캐릭터의 인벤토리는 모든 종류의
AMateria를 지원해야 함
IMateriaSourceclass IMateriaSource
{
public:
virtual ~IMateriaSource() {}
virtual void learnMateria(AMateria*) = 0;
virtual AMateria* createMateria(std::string const &type) = 0;
};
MateriaSourceIMateriaSource 상속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);
}