서적 정리/C++ 기초 플러스

79.추상화 기초 클래스

민돌이2 2022. 7. 14. 15:24

추상화 기초 클래스(abstract base class : ABC)는 공통된 부분이 많지만, 어느 한 쪽에 속하지 않는 관계일 때, 공통된 멤버들만으로 정의한 클래스를 의미한다. 언제 사용할 수 있을까?

 

public 상속일 때, is-a 관계로 예를 들어보자.

타원과 원을 생각해봤을 때, 타원이란 장경과 단경의 길이가 다른 것을 의미하고, 원은 장경과 단경이 같은 원을 의미한다. 즉, 원은 타원에 포함되어 있다. 따라서 public 상속으로 설계할 수 있는데 이는 많은 문제점이 발생한다.

class Ellipse
{
public:
	...
	void Move(int nx, int ny) { x = nx; y = ny; }
	virtual double Area() const { return 3.14159 * a * b; }
	virtual void Rotate()(double nangle) {angle = nangle; }
	virtual void Scale(double sa, double sb) { a *= sa; b *= sb; }

private:
	double x; //타원의 중심 x 좌표
	double y; //타원의 중심 y 좌표
	double a; //반장경
	double b; //반단경
	double angle; //각도 단위

};

class Circla : public Ellipse
{
	...
};

장경과 단경의 경우는 같은 값을 대입함으로써 해결할 수 있지만, angle변수와 Rotate 함수는 의미가 없다.

Circle 클래스에 private 멤버로 Rotate() 함수를 재정의하는 방법이 있을 순 있지만, 이런 코드가 많아질 수록 쓸모없는 용량이 늘어난다는 것이므로 자원낭비가 된다.

이런 문제점의 해결책으로 추상화 기초 클래스를 구현하는 것이다. Ellipse와 Circle 클래스의 공통적인 것들을 추출하여 추상화 기초 클래스(ABC)로 만들고 Ellipse와 Circle 클래스 모두 ABC로부터 파생시키는 것이다.

class BaseEllipse
{
public:
	BaseEllipse(double x0 = 0, double y0 = 0)
		: x(x0), y(y0)
	{ }
	virtual ~BaseEllipse() {}

	void Move(int nx, int ny) { x = nx; y = ny; }
	virtual double Area() const = 0; //순수 가상 함수
	...

private:
	double x;
	double y;
	...
};

class Ellipse : public BaseEllipse
{
	...
};

class Circle : public BaseEllipse
{
	...
};

순수 가상 함수를 사용했다는 점을 주목해야한다. 클래스 선언에 순수 가상 함수가 한 개라도 존재하면, 추상화 기초 클래스가 되고, 그 클래스의 객체를 생성할 수 없다. 또한 인터페이스(Interface)라고도 부른다. 가상 함수의 경우 파생 클래스에서 재정의 하지 않아도 문제가 없었지만, 순수 가상 함수의 경우 파생 클래스에서 반드시 재정의해야 하는 강제성이 생긴다.

728x90