=> 먼저 알아야 할것은 상속, 재정의-overriding, 가상함수-동적 바인딩
(객체 사용)
=>업캐스팅( upcasting ) 상황에서 재정의 멤버함수를 호출한다.
객체를 사용한다? 객체가 가지는 공개된 동작을 호출한다. -> 인스턴스 화 시킴.
자식보다 부모가 더 큰 타입이다.
업캐스팅
-> 자식 클래스 타입( 작은타입 )을 부모 클래스타입( 큰 타입 )으로 변환
-> 부모클래스 타입 포이턴 // 레퍼런스 변수에 자식 객체를 대입한다.
다운캐스팅
-> 부모 클래스 타입을 자식 클래스타입으로 변환
shape *ps = new Circle(); // 부모가 더 큰 타입이라 작은 타입을 변환 가능하다.
class Shape {
protected:
int x, y;
public:
void setOrigin(int x, int y){
this->x = x;
this->y = y;
}
cout <<"Shape Draw";
}
};
class Rectangle : public Shape {
private:
int width, height;
public:
void setWidth(int w) {
width = w;
}
void setHeight(int h) {
height = h;
}
void draw() {
cout << "Rectangle Draw";
}
};
int main()
{
Shape *ps = new Rectangle(); // 업
ps->setOrigin(10, 10);
ps->draw();
((Rectangle *)ps)->setWidth(100); // 다운캐스팅.
delete ps;
Circle c;
Shape &s = c; // OK!
s.setOrigin(10, 10);
s.draw();
((Circle *)ps)->setRadius(5); // Circle의 setRadius() 호출
}
-> 정적 바인딩이라서 Shape의 Draw가 나온다.
-> 동적 바인딩을 할려면?
virtual void draw() {
cout <<"Shape Draw";
}
void move(Shape& s, int sx, int sy)
{
s.setOrigin(sx, sy);
}
int main()
{
Rectangle r;
move(r, 0, 0);
Circle c;
move(c, 10, 10);
return 0;
}
- > 함수를 만들때 매개변수의 타입을 높이는것이 좋다.
자식 클래스는 모두 사용이 가능하기 때문
Shape *arrayShape[3]
-> Shape 형태의 포인터 배열이다.
다형성의 정의
- 객체에 따라서 다른 결과를 지닐수 있다.
구현(설계)
- 클래스와 상속관계(is-a), 멤버 함수의 재정의(Overriding), virtual함수로 구현( 동적 바인딩 )
사용하는 측면
- 업 캐스팅을 통한 재정의가 필요하다.
장점
- 확장성이 증가된다( 유지보수 용이. )