C++ 객체지향프로그래밍 수업
[C++] 9주차 실습: 추상 클래스 구현 연습, HDC
인생 걸고 삽질
2022. 12. 7. 01:57
9주차 실습
이번 시간에는 추상 클래스 구현하기를 연습한다.
QUIZ 01
#include<iostream>
using namespace std;
class Shape {
protected: virtual void draw() = 0;
public:
Shape() {}
virtual ~Shape() {}
void paint();
};
void Shape::paint() { draw(); }
class Circle :public Shape {
virtual void draw() override;
};
void Circle::draw(){ cout << "Circle\n"; }
class Rect :public Shape {
virtual void draw() override;
};
void Rect::draw() { cout << "Rect\n"; }
class Line :public Shape {
virtual void draw() override final;
};
void Line::draw() { cout << "Line\n"; }
int main() {
Shape* shapeArr[3];
shapeArr[0] = new Circle();
shapeArr[1] = new Rect();
shapeArr[2] = new Line();
for (int i = 0; i < 3; i++) {
shapeArr[i]->paint();
}
for (int i = 0; i < 3; i++) {
delete shapeArr[i];
}
}
- virtual function을 이용하면 부모 클래스의 포인터를 역참조해서 자식 클래스의 함수를 사용할 수 있다는... 기본적인 추상 클래스의 역할을 가르쳐 주고 싶으셨던 듯하다.
QUIZ 02
#include<iostream>
using namespace std;
class Calculator {
public:
virtual int add(int a, int b) = 0;
virtual int sub(int a, int b) = 0;
virtual double average(int a[], int size) = 0;
};
class GoodCalc : public Calculator {
virtual int add(int a, int b) override final;
virtual int sub(int a, int b) override final;
virtual double average(int a[], int size) override final;
};
int GoodCalc::add(int a, int b) {
return (a + b);
}
int GoodCalc::sub(int a, int b) {
return (a - b);
}
double GoodCalc::average(int a[], int size) {
double sum = 0;
for (int i = 0; i < size; i++) sum += a[i];
return (sum / size);
}
int main() {
int a[] = { 1,2, 3, 4, 5 };
Calculator* p = new GoodCalc();
cout << p->add(2, 3) << endl;
cout << p->sub(2, 3) << endl;
cout << p->average(a, 5) << endl;
}
- virtual 함수가 여러 개여도 상관 없다는 걸 가르치고 싶으셨던 듯하다.
QUIZ 03
#include<iostream>
using namespace std;
class Calculator {
protected:
int a, b;
virtual int calc(int a, int b) = 0;
public:
void run() {
input();
cout << "rusult: " << calc(a, b) << endl;
}
private:
void input() {
cout << "Enter 2 integers\n[ENTER] ";
cin >> a >> b;
}
};
class Adder :public Calculator {
virtual int calc(int a, int b) override;
};
int Adder::calc(int a, int b) { return (a + b); }
class Subtractor :public Calculator {
virtual int calc(int a, int b) override final;
};
int Subtractor::calc(int a, int b) { return (a - b); }
int main() {
Adder add;
Subtractor sub;
add.run();
sub.run();
}
- 같은 함수를 다른 클래스에서 overriding하면 이렇게 다형성을 이용할 수 있다는 걸 가르치고 싶으셨던 듯하다.
- 위 코드에서 run()이라는 함수는 같지만 각각 더하고 빼는, 다른 기능을 수행한다.
- 이런 걸 polymorphism이라고 한다.
- 이렇게 overriding해서 각기 다른 기능을 설정해 줬기 때문에 그러한 다형성을 사용 가능하다.
QUIZ 04
다시 한 번 구현해 보기
#include<iostream>
#include<windows.h>
using namespace std;
int newCursorX = 0; //X좌표가 0에 있는 커서를 하나 만든다.
class Shape {
protected:
HDC hdc; //HDC 객체를 하나 만든다. Shape node는 hdc node를 가지고 있다.
virtual void draw() = 0;
public:
Shape() {
hdc = GetWindowDC(GetForegroundWindow());
/* GetWindowDC(A): A창의 핸들을 가져다 주세요
GerForegroundWindow(): 가장 맨 앞에 떠 있는 창을 가져다 주세요.
hdc = GetWindowDC(GetForegroundWindow()): 맨 앞에 떠 있는 창의 핸들을 hdc에 저장하겠습니다.
*/
}
virtual ~Shape() {}
void paint();
};
void Shape::paint() { draw(); }
class Circle :public Shape {
virtual void draw() override;
};
class Rect :public Shape {
virtual void draw() override;
};
class Line :public Shape {
virtual void draw() override final;
};
void Circle::draw() {
Ellipse(hdc, newCursorX + 10, 100, newCursorX + 110, 200);
//Ellipse(핸들, top, right, bottom, left);
//hdc 핸들을 가지고 현재 CUrsorX의 위치에서 시계방향으로 10, 100, 110, 200을 기점으로 하는 원을 그리겠습니다.
newCursorX += 110;
//제 자리를 다 차지했으니 이제 다음 도형을 위해 마우스 커서를 110만큼 오른쪽으로 옮겨 주세요.
}
void Rect::draw() {
Rectangle(hdc, newCursorX + 10, 100, newCursorX + 110, 200);
newCursorX += 110;
}
void Line::draw() {
MoveToEx(hdc, newCursorX + 10, 100, NULL);
//MoveToEx(핸들 node, x좌표, y좌표, NULL): 핸들 node를 (x, y)로 옮겨 주세요.
LineTo(hdc, newCursorX + 110, 200);
//LineTo(핸들 node, x좌표, y좌표, NULL): 핸들 Node를 (x, y)까지 쭉 옮기면서 선을 긋겠습니다.
newCursorX += 110;
}
int main() {
Shape* shapeArr[3];
shapeArr[0] = new Circle();
shapeArr[1] = new Rect();
shapeArr[2] = new Line();
for (int i = 0; i < 3; i++) {
shapeArr[i]->paint();
}
for (int i = 0; i < 3; i++) {
delete shapeArr[i];
}
}
- 교수님께서 굳이 이 예제의 main함수를 quiz1과 똑같이 만드신 이유는, Quiz01에선 Circle()이 "CIrcle"을 출력하는 것처럼 Quiz04에서는 동그라미 모양을 그리는 기능인 것처럼, 같은 코드를 재활용하는 방법을 가르치기 위해서인 듯하다.
- 왜 내 머리속에서 타원이 Eclipse라고 굳어졌는지 모르겠는데... 타원은 이클립스가 아니라 엘립스다!