Download presentation
Presentation is loading. Please wait.
Published byἌρτεμις Σωτηρία Καλογιάννης Modified 6년 전
1
제12장 다형성과 가상함수 다형성의 개념을 이해한다. 상향 형변환의 개념을 이해한다. 가상 함수의 개념을 이해한다.
다형성을 실제로 적용할 수 있다.
2
이번 장에서 만들어 볼 프로그램
3
다형성이란?
4
실행시간 다형성 “실행 시간 다형성”이란 객체들의 타입이 다르면 똑같은 메시지가 전달되더라도 서로 다른 동작을 하는 것을 말한 다.
5
객체 포인터의 형변환 상향 형변환(upcasting): 자식 클래스 타입을 부모 클래스타입으로 변환 객체 포인터의 형변환
하향 형변환(downcasting): 부모 클래스 타입을 자식 클래스타입으로 변환
6
Animal 타입 포인터로 Dog 객체를 참조하니 틀린 거 같지만 올바른 문장!!
상속과 객체 포인터 Animal 타입 포인터로 Dog 객체를 참조하니 틀린 거 같지만 올바른 문장!! Animal *pa = new Dog();// OK!
7
왜 그럴까? 자식 클래스 객체는 부모 클래스 객체를 포함하고 있기 때문이다.
8
상향 형변환 #include <iostream> using namespace std; class Animal {
public: void speak() { cout << "Animal speak()" << endl; } }; class Dog : public Animal int age; void speak() { cout << "멍멍" << endl; } class Cat : public Animal void speak() { cout << "야옹" << endl; }
9
상향 형변환 int main() { Animal *a1 = new Dog(); a1->speak();
Animal *a2 = new Cat(); a2->speak(); //a1->age = 10; // 오류!! return 0; }
10
가상함수 Animal 포인터를 통하여 객체의 멤버 함수를 호출하더라 도 객체의 종류에 따라서 서로 다른 speak()가 호출된다 면 상당히 유용할 것이다.
11
에제 class Animal { public:
virtual void speak() { cout << "Animal speak()" << endl; } }; class Dog : public Animal int age; void speak() { cout << "멍멍" << endl; } class Cat : public Animal void speak() { cout << "야옹" << endl; }
12
에제 int main() { Animal *a1 = new Dog(); a1->speak();
Animal *a2 = new Cat(); a2->speak(); return 0; }
13
동적바인딩 vs 정적바인딩
14
도형 예제 #1
15
에제 #include <iostream> using namespace std; class Shape {
protected: int x, y; public: Shape(int x, int y) : x(x), y(y) { } virtual void draw() { cout << "Shape Draw" << endl; } };
16
에제 class Rect: public Shape { private: int width, height; public:
Rect(int x, int y, int w, int h) : Shape(x, y), width(w), height(h) { } void draw() { cout << "Rectangle Draw" << endl; };
17
예제 int main() { Shape *ps = new Rect(0, 0, 100, 100); // OK!
ps->draw(); delete ps; return 0; }
18
도형 예제 #2
19
에제 class Shape { protected: int x, y; public:
Shape(int x, int y) : x(x), y(y) { } virtual void draw() { cout << "Shape Draw" << endl; } }; class Rect : public Shape { private: int width, height; Rect(int x, int y, int w, int h) : Shape(x, y), width(w), height(h) { } void draw() { HDC hdc = GetWindowDC(GetForegroundWindow()); Rectangle(hdc, x, y, x + width, y + height);
20
에제 class Circle : public Shape { private: int radius; public:
Circle(int x, int y, int r) : Shape(x, y), radius(r) { } void draw() { HDC hdc = GetWindowDC(GetForegroundWindow()); Ellipse(hdc, x - radius, y - radius, x + radius, y + radius); } }; int main() { Shape *shapes[3]; shapes[0] = new Rect(rand() % 600, rand() % 300, rand() % 100, rand() % 100); shapes[1] = new Circle(rand() % 600, rand() % 300, rand() % 100); shapes[2] = new Circle(rand() % 600, rand() % 300, rand() % 100); for (int i = 0; i < 3; i++) { shapes[i]->draw(); 에제
21
에제
22
참조자와 가상함수 참조자도 포인터와 마찬가지로 모든 것이 동일하게 적용 된다. 즉 부모 클래스의 참조자로 자식 클래스를 가리킬 수 있으며 가상 함수의 동작도 동일하다.
23
가상소멸자 다형성을 사용하는 과정에서 소멸자를 virtual로 해주지 않으면 문제가 발생한다.
#include <iostream> using namespace std; class Parent { public: ~Parent() { cout << "Parent 소멸자" << endl; } };
24
가상소멸자 class Child : public Parent { public:
~Child() { cout << "Child 소멸자" << endl; } }; int main() Parent* p = new Child(); // 상향 형변환 delete p; }
25
해결책 class Parent { public:
virtual ~Parent() { cout << "Parent 소멸자" << endl; } };
26
순수가상함수 class Shape { protected: int x, y; public:
Shape(int x, int y) : x(x), y(y) { } virtual void draw() = 0; }; class Rect : public Shape { private: int width, height; Rect(int x, int y, int w, int h) : Shape(x, y), width(w), height(h) { } void draw() { cout << "Rectangle Draw" << endl; }
27
순수가상함수 int main() { Shape *ps = new Rect(0, 0, 100, 100); // OK!
ps->draw(); // Rectangle의 draw()가 호출된 다. delete ps; return 0; }
28
Lab: 동물 예제
29
Solution class Animal { virtual void move() = 0;
virtual void eat() = 0; virtual void speak() = 0; }; class Lion : public Animal { void move(){ cout << "사자의 move() << endl; } void eat(){ cout << "사자의 eat() << endl; void speak(){ cout << "사자의 speak() << endl;
30
Lab: 인터페이스
31
Solution class RemoteControl { // 순수 가상 함수 정의
virtual void turnON() = 0; // 가전 제품을 켠다. virtual void turnOFF() = 0; // 가전 제품을 끈다. } class Television : public RemoteControl { void turnON() { // 실제로 TV의 전원을 켜기 위한 코드가 들어 간다. ... void turnOFF() // 실제로 TV의 전원을 끄기 위한 코드가 들어 간다.
32
Lab: 던전 게임
33
Solution class Sprite { protected: int x, y; // 현재 위치 char shape;
public: Sprite(int x, int y, char shape) : x{ x }, y{ y }, shape{ shape } { } virtual ~Sprite() { } virtual void move(char d) = 0; char getShape() { return shape; } int getX() { return x; } int getY() { return y; } bool checkCollision(Sprite *other) { if (x == other->getX() && y == other->getY()) return true; else } };
34
Solution // 주인공 스프라이트를 나타낸다. class Hero : public Sprite { public:
Hero(int x, int y) : Sprite(x, y, 'H') { } void draw() { cout << 'H'; } void move(char d) { if (d == 'a') { x -= 1; } else if (d == 'w') { y -= 1; } else if (d == 's') { y += 1; } else if (d == 'd') { x += 1; } } }; // 보물을 나타내는 클래스이다. class Treasure : public Sprite { Treasure(int x, int y) : Sprite(x, y, 'T') { }
35
Solution class Enemy : public Sprite { public:
Enemy(int x, int y) : Sprite(x, y, 'E') { } void move(char d) { } }; // 게임 보드를 표시한다. class Board { char *board; int width, height; Board(int w, int h) : width{ w }, height{ h } { board = new char[width*height]; clearBoard(); } ~Board() { delete board;
36
Solution void setValue(int r, int c, char shape) {
board[r*width + c] = shape; } void printBoard() { for (int i = 0; i < height; i++) { cout << "\t"; for (int j = 0; j < width; j++) cout << board[i*width + j]; cout << endl; void clearBoard() { for (int i = 0; i < height; i++) board[i*width + j] = '.'; }; void drawLine(char x) { for (int i = 0; i < 100; i++) cout << x; Solution
37
Solution int main() { // 벡터를 사용하여 게임에서 나타나는 모든 스프라이트들을 저장한다.
// 다형성을 사용해야 하므로 포인터를 벡터에 저장한다. // 다형성은 포인터를 이용해야 사용할 수 있음을 잊지 말자. vector<Sprite *> list; int width, height; cout << "보드의 크기를 입력하시오[최대 10X10]: " << endl; cout << "가로: "; cin >> width; cout << "세로: "; cin >> height; Board board(height, width); list.push_back(new Hero(0, 0)); list.push_back(new Treasure(height - 1, width - 1)); list.push_back(new Enemy(3, 3)); Solution
38
Solution // 게임 루프이다. while (true) { // 보드를 다시 그린다. board.clearBoard();
for (auto& e : list) board.setValue(e->getY(), e->getX(), e- >getShape()); board.printBoard(); // 사용자의 입력을 받는다. char direction; cout << "어디로 움직일까요(a, s, w, d): "; cin >> direction; // 모든 스프라이트를 이동시킨다. e->move(direction); drawLine('-'); } Solution
39
Solution // 벡터 안의 모든 동적 할당을 해제한다. for (auto& e : list) delete e;
list.clear(); return 0; }
40
Q & A
Similar presentations