다형성(polymorphism)
동일한 메시지에 대하여 객체에 따라 다른 동작을 하는 것 예) Draw(그리다)라는 메시지가 circle객체와 rectangle객체
에서 다르게 동작함
Cry(울다)라는 메시지가 dog객체와 bird객체에서 다르
게 동작함
다형성의 구현
기본적으로 함수 재정의를 사용함 예)
클래스명 : Animal
멤버함수 : void Cry();
// 울음
클래스명 : Dog
멤버함수 : void Cry();
// 멍멍
클래스명 : Bird
멤버함수 : void Cry();
// 짹짹
int main() { Dog a;
Bird b;
a.Cry();
b.Cry();
return 0;
}
// 다형성 프로그램
#include <iostream>
using namespace std;
class Animal{
public:
void Cry(){
cout << "울음\n"; return; } };class Dog : public Animal{
public:
void Cry(){
cout << "멍멍\n"; return; } };class Bird : public Animal{
public:
void Cry(){
cout << "짹짹\n"; return; };
};
int main( ) { Dog a;
Bird b;
a.Cry();
b.Cry();
return 0;
}
다형성의 구현
- 의미있는 다형성은 객체 포인터(참조자)를 사용함
- 상향 형변환(up-casting) : 자식클래스의 주소값을 부모 클래스의 포인터에 저장할 수 있으나 부모클래스의 멤버만 접근가능함
예) Dog a;
Animal *p = &a;
- 하향 형변환(down-casting) : 부모클래스의 포인터에 저 장된 자식클래스의 주소값을 자식클래스의 포인터에 저장 할 수 있음, 이때는 강제 형변환이 필요함
예) Animal *p = new Dog;
Dog *pd = (Dog *) p;
예)
클래스명 : Animal
멤버함수 : void Cry();
// 울음
클래스명 : Dog
멤버함수 : void Cry();
// 멍멍
클래스명 : Bird
멤버함수 : void Cry();
// 짹짹
int main()
{ Animal *pa = new Dog;
Animal *pb = new Bird;
pa->Cry();
pb->Cry();
Dog *pd = (Dog *) pa;
pd->Cry();
return 0;
}
가상함수(virtual function)
- 부모클래스의 포인터로 자식클래스의 함수를 호출하려 면 부모클래스의 함수를 가상함수로 선언함
- 함수헤더 앞에 예약어 virtual 을 붙이면 가상함수로 선 언됨
형식) virtual 반환자료형 함수명(매개변수리스트);
- 부모클래스의 함수가 가상함수이면 자식클래스의 함수 는 자동적으로 가상함수가 됨(virtual이 없어도 가상함수임) - 가상함수란 함수 호출시 어떤 함수를 사용할 것인지를 컴파일할 때 결정하지 않고, 함수가 호출될 때 결정하는 동 적바인딩(dynamic binding) 함수임
※ 정적바인딩(static binding)
// 가상함수 프로그램
#include <iostream>
using namespace std;
class Animal{
public:
virtual void Cry(){
cout << "울음\n"; return; } };class Dog : public Animal{
public:
void Cry(){
cout << "멍멍\n"; return; } };class Bird : public Animal{
public:
void Cry(){
cout << "짹짹\n"; return; };
};
int main()
{ Animal *pa = new Dog;
Animal *pb = new Bird;
pa->Cry();
pb->Cry();
Dog *pd = (Dog *) pa;
pd->Cry();
return 0;
}
// 가상함수와 다형성 프로그램
#include <iostream>
using namespace std;
class Animal{
public:
virtual void Cry(){
cout << "울음\n"; return; } };class Dog : public Animal{
public:
void Cry(){
cout << "멍멍\n"; return; } };class Bird : public Animal{
public:
void Cry(){
cout << "짹짹\n"; return; };
};
void Animal_cry(Animal &);
int main( ) { Dog a;
Bird b;
Animal_cry(a);
Animal_cry(b);
return 0;
}
void Animal_cry(Animal& pa) { pa.Cry();
return;
}
가상함수의 동작 원리
- 가상함수가 있는 부모클래스에 가상함수테이블이 생성 되어 부모클래스의 함수 주소가 저장됨
- 자식클래스에서 가상함수가 재정의되면, 부모클래스의 가상함수테이블에 자식클래스의 함수 주소가 저장됨
- 가상함수가 호출되면 가상함수테이블에 저장된 함수가 호출되어 실행됨
가상함수와 다형성
- 가상함수는 다형성을 구현하는 수단으로 다형성이란
하나의 형으로 여러 가지 형을 구현한다는 의미임
순수가상함수(pure virtual function)
- 순수가상함수란 함수헤더만 존재하고 함수몸체는 없는 함수임
형식) virtual 반환자료형 함수명(매개변수리스트) = 0;
추상클래스(abstract class)
- 순수가상함수를 가진 클래스를 추상클래스라고 함 - 추상클래스는 객체를 생성할 수 없음
- 추상클래스를 상속받은 자식클래스는 반드시 순수가상
함수를 구현해야 함
// 순수가상함수 프로그램
#include <iostream>
using namespace std;
class Animal{
public:
virtual void Cry() = 0;
};class Dog : public Animal{
public:
void Cry(){
cout << "멍멍\n"; return; } };class Bird : public Animal{
public:
void Cry(){
cout << "짹짹\n"; return; };
};
int main()
{ Animal *pa = new Dog;
Animal *pb = new Bird;
pa->Cry();
pb->Cry();
Dog *pd = (Dog *) pa;
pd->Cry();
return 0;
}