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라고 굳어졌는지 모르겠는데... 타원은 이클립스가 아니라 엘립스다!