抽象クラス

  クラスは,次の例のように,0 に初期化された仮想関数を含むと抽象クラスになります.0 に初期化された仮想関数を純粋仮想関数といいます.派生したクラスは,それが,非抽象クラスであれば,その基底クラスのすべての純粋仮想関数を定義(オーバーライド)してやる必要があります.

/****************************/
/* 抽象クラス               */
/*      coded by Y.Suganuma */
/****************************/
#include <iostream>
#include <math.h>
#include <stdlib.h>

/****************/
/* クラスFigure */
/****************/
class Figure {
	public:
		double s;   // 図形の面積
		virtual void input() = 0;   // データの入力,純粋仮想関数
		virtual void menseki() = 0;   // 面積の計算,純粋仮想関数
		void print(int sw)   // 結果の出力
		{
			if (sw == 0)
				std::cout << "   与えられた楕円の面積は " << s << " です\n";
			else
				std::cout << "与えられた多角形の面積は " << s << " です\n";
		}
};

/*****************/
/* クラスEllipse */
/*****************/
class Ellipse : public Figure {
		double a, b;   // 楕円の長径と短径
	public:
		void input()   // データの入力
		{
			std::cout << "楕円の長径は? ";
			std::cin >> a;
			std::cout << "楕円の短径は? ";
			std::cin >> b;
		}
		void menseki()   // 楕円の面積
		{
			s = 4.0 * atan(1.0) * a * b;
		}
};

/*****************/
/* クラスPolygon */
/*****************/
class Polygon : public Figure {
		int n;   // 点の数
		int *m;   // 点の番号
		double **p;   // 各点の座標
		double men(int, double **, int *);
		double sankaku(int, int, int *, double **);
		int check1(int, int, int *, double **);
		int check2(int, int, int *, double **);
	public:
					// コンストラクタ
		Polygon (int n1)
		{
			if (n1 < 3) {
				std::cout << "3点以上与えてください\n";
				exit(1);
			}
			else {
				n = n1;
				m = new int [n];
				p = new double * [n];
				for (int i1 = 0; i1 < n; i1++)
					p[i1] = new double [2];
			}
		}
					// デストラクタ
		~Polygon ()
		{
			if (n > 0) {
				for (int i1 = 0; i1 < n; i1++)
					delete [] p[i1];
				delete [] p;
				delete [] m;
			}
		}
					// データの入力
		void input()
		{
			std::cout << "各点の座標の入力(反時計回り)\n";
			for (int i1 = 0; i1 < n; i1++) {
				std::cout << "   " << i1+1 << " 番目の点のx座標は? ";
				std::cin >> p[i1][0];
				std::cout << "      " << i1+1 << " 番目の点のy座標は? ";
				std::cin >> p[i1][1];
			}
		}
					// 多角形の面積
		void menseki()
		{
			for (int i1 = 0; i1 < n; i1++)
				m[i1] = i1;
			s = men(n, p, m);
		}
};

/******************************/
/* 多角形の面積を再帰的に計算 */
/*      n : 点の数            */
/*      p : 点の座標          */
/*      m : 点番号            */
/*      return : 面積         */
/******************************/
double Polygon::men(int n, double **p, int *m)
{
	double s = 0.0;
	if (n == 3)   // 三角形
		s = sankaku(n, 0, m, p);
	else {
		int sw1 = 0;
		for (int i1 = 0; i1 < n && sw1 == 0; i1++) {
			int sw = check1(n, i1, m, p);   // 多角形の中?
			if (sw == 0) {
				sw = check2(n, i1, m, p);   // 中に他の点がある?
				if (sw == 0) {
					s = sankaku(n, i1, m, p);   // i1から始まる三角形
					for (int i2 = i1+1; i2 < n-1; i2++)   // 点を除く
						m[i2] = m[i2+1];
					s   += men(n-1, p, m);   // (n-1)この点からなる多角形
					sw1  = 1;
				}
			}
		}
	}
	return s;
}

/***********************/
/* 三角形の面積の計算  */
/*      n : 点の数     */
/*      k : 開始点番号 */
/*      m : 点番号     */
/*      p : 点の座標   */
/*      return : 面積  */
/***********************/
double Polygon::sankaku(int n, int k, int *m, double **p)
{
	int k1 = m[k];
	int k2 = (k == n-1) ? m[0] :m[k+1];
	int k3;
	if (k < n-2)
		k3 = m[k+2];
	else
		k3 = (k == n-2) ? m[0] : m[1];
	double x1 = p[k2][0] - p[k1][0];
	double y1 = p[k2][1] - p[k1][1];
	double r1 = sqrt(x1 * x1 + y1 * y1);
	double t1 = atan2(y1, x1);
	x1 = p[k3][0] - p[k1][0];
	y1 = p[k3][1] - p[k1][1];
	double r2 = sqrt(x1 * x1 + y1 * y1);
	double t2 = atan2(y1, x1);
	double t3 = t2 - t1;
	double s = fabs(0.5 * r1 * r2 * sin(t3));
	return s;
}

/****************************************/
/* 三角形が多角形の内部か否かのチェック */
/*       n : 点の数                     */
/*       k : 開始点番号                 */
/*       m : 点番号                     */
/*       p : 点の座標                   */
/*       return : =0 : 内部である       */
/*                =1 : 内部でない       */
/****************************************/
int Polygon::check1(int n, int k, int *m, double **p)
{
	double pi = 4.0 * atan2(1.0, 1.0);
	int k1 = m[k];
	int k2 = (k == n-1) ? m[0] :m[k+1];
	int k3;
	if (k < n-2)
		k3 = m[k+2];
	else
		k3 = (k == n-2) ? m[0] : m[1];
	double x1 = p[k3][0] - p[k1][0];
	double y1 = p[k3][1] - p[k1][1];
	double t1 = atan2(y1, x1);
	x1 = p[k2][0] - p[k1][0];
	y1 = p[k2][1] - p[k1][1];
	double t2 = atan2(y1, x1);
	double t3 = t2 - t1;
	if (t3 > pi)
		t3 -= 2.0 * pi;
	else {
		if (t3 < -pi)
			t3 += 2.0 * pi;
	}
	int sw = 0;
	if (t3 > 0.0)
		sw = 1;
	return sw;
}

/************************************************/
/* 三角形内に他の頂点が存在するか否かのチェック */
/*      n : 点の数                              */
/*      k : 開始点番号                          */
/*      m : 点番号                              */
/*      p : 点の座標                            */
/*      return : =0 : 存在しない                */
/*               =1 : 存在する                  */
/************************************************/
int Polygon::check2(int n, int k, int *m, double **p)
{
	double pi = 4.0 * atan2(1.0, 1.0);
	int k1 = m[k];
	int k2 = (k == n-1) ? m[0] :m[k+1];
	int k3, sw = 0;
	if (k1 < n-2)
		k3 = m[k+2];
	else
		k3 = (k == n-2) ? m[0] : m[1];
	double x1  = p[k2][0] - p[k1][0];
	double y1  = p[k2][1] - p[k1][1];
	double t10 = atan2(y1, x1);
	x1  = p[k3][0] - p[k2][0];
	y1  = p[k3][1] - p[k2][1];
	double t11 = atan2(y1, x1);
	x1  = p[k1][0] - p[k3][0];
	y1  = p[k1][1] - p[k3][1];
	double t12 = atan2(y1, x1);
	for (int i1 = 0; i1 < n && sw == 0; i1++) {
		if (i1 != k1 && i1 != k2 && i1 != k3) {
			x1 = p[m[i1]][0] - p[k1][0];
			y1 = p[m[i1]][1] - p[k1][1];
			double t2 = atan2(y1, x1);
			double t3 = t2 - t10;
			if (t3 > pi)
				t3 -= 2.0 * pi;
			else {
				if (t3 < -pi)
					t3 += 2.0 * pi;
			}
			if (t3 > 0.0) {
				x1 = p[m[i1]][0] - p[k2][0];
				y1 = p[m[i1]][1] - p[k2][1];
				double t2 = atan2(y1, x1);
				t3 = t2 - t11;
				if (t3 > pi)
					t3 -= 2.0 * pi;
				else {
					if (t3 < -pi)
						t3 += 2.0 * pi;
				}
				if (t3 > 0.0) {
					x1 = p[m[i1]][0] - p[k3][0];
					y1 = p[m[i1]][1] - p[k3][1];
					t2 = atan2(y1, x1);
					t3 = t2 - t12;
					if (t3 > pi)
						t3 -= 2.0 * pi;
					else {
						if (t3 < -pi)
							t3 += 2.0 * pi;
					}
					if (t3 > 0.0)
						sw = 1;
				}
			}
		}
	}
	return sw;
}

/*************/
/* main 関数 */
/*************/
int main()
{
/*
	 楕円
*/
	Ellipse e1;

	e1.input();
	e1.menseki();
	e1.print(0);

/*
	 多角形
*/
	int n;

	std::cout << "点の数は? ";
	std::cin >> n;

	Polygon p1(n);

	p1.input();
	p1.menseki();
	p1.print(1);

	return 0;
}