728x90
황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!
https://search.shopping.naver.com/book/catalog/32436115747
가상 함수는 파생 클래스에서 오버라이딩할 함수를 알려주는 인터페이스의 역할을 한다. 응용 사례를 다루며 아래 4가지 주제에 대해 알아보자.
- 가상 함수를 가진 기본 클래스의 목적
- 가상 함수 오버라이딩
- 동적 바인딩 실행
- 기본 클래스의 포인터 활용
가상 함수를 가진 기본 클래스의 목적
- Shape은 Circle, Rect, Line 등 도형의 공통 속성을 구현하는 기본 클래스의 역할을 한다.
- Shape은 가상 함수 draw()를 선언하여, 파생 클래스에서 draw()를 오버라이딩하여 자신의 도형을 그리도록 유도한다.
- 즉, 구체적인 도형을 묘사하지 않는 Shape 클래스는 Shape 객체를 생성하려는 의도로 만들어진 것은 아니다.
가상 함수 오버라이딩 : 파생 클래스마다 다르게 구현하는 다형성
- 파생 클래스들은 가상 함수인 draw() 함수를 오버라이딩 함으로써 어떤 경우에도 자신이 만든 draw() 함수가 호출되는 것을 보장받는다.
- 또한, Circle, Rect, Line이 draw() 함수를 다음과 같이 다르게 구현한다는 점에 주목해보자.
void Circle::draw() {
cout << "Circle" << endl;
}
void Line::draw() {
cout << "Line" << endl;
}
void Rect::draw() {
cout << "Rectangle" << endl;
}
동적 바인딩 실행 : 파생 클래스의 가상 함수 실행
- Circle, Rect, Line 클래스를 활용하여 원, 사각형, 선 등의 도형을 생성하고 이들을 링크드 리스트로 연결하여 관리하는 코드를 작성해보자.
- main() 함수는 Circle, Rect, Line, Rect 객체를 순서대로 생성하여 링크드 리스트로 연결한다.
- pStart 포인터가 처음 객체를, pLast 포인터가 마지막 객체를 가리킨다.
#include <iostream>
#include "Shape.h"
#include "Circle.h"
#include "Rect.h"
#include "Line.h"
using namespace std;
int main() {
Shape *pStart=NULL;
Shape *pLast;
pStart = new Circle(); // 처음에 원 도형을 생성한다.
pLast = pStart;
pLast = pLast->add(new Rect()); // 사각형 객체 생성
pLast = pLast->add(new Circle()); // 원 객체 생성
pLast = pLast->add(new Line()); // 선 객체 생성
pLast = pLast->add(new Rect()); // 사각형 객체 생성
// 현재 연결된 모든 도형을 화면에 그린다.
Shape* p = pStart;
while(p != NULL) {
p->paint();
p = p->getNext();
}
// 현재 연결된 모든 도형을 삭제한다.
p = pStart;
while(p != NULL) {
Shape* q = p->getNext(); // 다음 도형 주소 기억
delete p; // 기본 클래스의 가상 소멸자 호출
p = q; // 다음 도형 주소를 p에 저장
}
}
/*
Circle
Rectangle
Circle
Line
Rectangle
*/
- 동적 바인딩이 가장 화려하게 꽃피는 곳은 바로 다음 코드이다.
- Shape 타입의 포인터 p를 이용하여 모든 도형을 방문하며 paint() 함수를 호출하면, paint()는 동적 바인딩을 통해 Circle, Rect, Line 클래스에 재정의된 각 draw() 함수를 호출한다.
// 현재 연결된 모든 도형을 화면에 그린다.
Shape* p = pStart;
while(p != NULL) {
p->paint();
p = p->getNext();
}
기본 클래스의 포인터 활용
- 또 하나 유의해서 볼 부분은 pStart, pLast, p의 타입이다.
- 모두 기본 클래스 Shape에 대한 포인터이다.
- 따라서 pLast는 Shape를 상속받은 어떤 객체든지 가리킬 수 있으므로, 링크드 리스트를 따라 이동하면서 파생 클래스의 객체들을 삽입할 수 있다.
- p의 경우 링크드 리스트를 따라 이동하면서 Shape의 paint()를 호출하여, 동적 바인딩으로 각 파생 클래스의 draw()를 호출하는 상황을 만들어낸다.
728x90
'Programming Language > C++' 카테고리의 다른 글
[C++] 템플릿 (0) | 2023.12.19 |
---|---|
[C++] 추상 클래스 (1) | 2023.12.19 |
[C++] 오버라이딩 (0) | 2023.12.18 |
[C++] 가상 함수와 오버라이딩 (1) | 2023.12.18 |
[C++] 다중 상속과 가상 상속 (0) | 2023.12.15 |