| 情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |
class クラス名 : [アクセス権] 基底クラス名 [,[アクセス権] 基底クラス・・・] {
変更部分
}
class der : Base {
・・・・・
public:
using Base::z; // 基底クラスBaseのパブリックメンバー変数
using Base::fun; // 基底クラスBaseのパブリックメンバー関数
・・・・・
};
クラス名 :: クラス名 (引数リスト) : 基底クラス名(パラメータリスト) [, 基底クラス名(パラメータリスト)・・・]
{
このクラスに必要な初期設定
}
01 /****************************/
02 /* 派生クラス */
03 /* coded by Y.Suganuma */
04 /****************************/
05 #include <iostream>
06
07 /********************/
08 /* クラスOya1の定義 */
09 /********************/
10 class Oya1 {
11 int priv1;
12 protected:
13 int prot1;
14 public:
15 int pub1;
16 Oya1 (int n1, int n2, int n3) // コンストラクタ
17 {
18 priv1 = n1;
19 prot1 = n2;
20 pub1 = n3;
21 }
22 void output1(int sw) // 出力
23 {
24 switch (sw) {
25 case 0:
26 std::cout << " priv1 " << priv1 << std::endl;
27 break;
28 case 1:
29 std::cout << " prot1 " << prot1 << std::endl;
30 break;
31 case 2:
32 std::cout << " pub1 " << pub1 << std::endl;
33 break;
34 }
35 }
36 };
37
38 /********************/
39 /* クラスOya2の定義 */
40 /********************/
41 class Oya2 {
42 int priv2;
43 public:
44 int pub2_1, pub2_2;
45 void set(int sw, int n) // 値の設定
46 {
47 switch (sw) {
48 case 0:
49 priv2 = n;
50 break;
51 case 1:
52 pub2_1 = n;
53 break;
54 case 2:
55 pub2_2 = n;
56 break;
57 }
58 }
59 void output2(int sw) // 出力
60 {
61 switch (sw) {
62 case 0:
63 std::cout << " priv2 " << priv2 << std::endl;
64 break;
65 case 1:
66 std::cout << " pub2_1 " << pub2_1 << std::endl;
67 break;
68 case 2:
69 std::cout << " pub2_2 " << pub2_2 << std::endl;
70 break;
71 }
72 }
73 };
74
75 /**********************/
76 /* クラスkodomoの定義 */
77 /**********************/
78 class Kodomo : public Oya1, Oya2 {
79 public:
80 // コンストラクタ(基底クラスのコンストラクタのために必要)
81 Kodomo (int n1, int n2, int n3) : Oya1(n1, n2, n3) {}
82 void output_k(int sw) // 出力
83 {
84 switch (sw) {
85 case 0: // 親のprivate変数にはアクセスできない
86 std::cout << " priv1 ?" << std::endl;
87 break;
88 case 1:
89 std::cout << " prot1 " << prot1 << std::endl;
90 break;
91 case 2:
92 std::cout << " pub1 " << pub1 << std::endl;
93 break;
94 case 3: // 親のprivate変数にはアクセスできない
95 std::cout << " priv2 ?" << std::endl;
96 break;
97 case 4:
98 std::cout << " pub2_1 " << pub2_1 << std::endl;
99 break;
100 case 5:
101 std::cout << " pub2_2 " << pub2_2 << std::endl;
102 break;
103 }
104 }
105 // Oya2のpublic変数の一部と関数をpubulicに移動
106 Oya2::pub2_1;
107 Oya2::set;
108 Oya2::output2;
109 };
110
111 /******************/
112 /* mainプログラム */
113 /******************/
114 int main()
115 {
116 // 親1
117 Oya1 o1(10, 20, 30);
118
119 std::cout << "親1\n";
120 o1.output1(0); // priv1 の出力
121 o1.output1(1); // prot1 の出力
122 o1.output1(2); // pub1 の出力
123 std::cout << " (from main) priv1 ? prot1 ? pub1 " << o1.pub1 << std::endl;
124 // 親2
125 Oya2 o2;
126
127 std::cout << "親2\n";
128 o2.set(0, 50);
129 o2.set(1, 60);
130 o2.set(2, 70);
131 o2.output2(0); // priv2 の出力
132 o2.output2(1); // pub2_1 の出力
133 o2.output2(2); // pub2_2 の出力
134 std::cout << " (from main) priv2 ? pub2_1 " << o2.pub2_1 << " pub2_2 " << o2.pub2_2 << std::endl;
135 // 子供
136 Kodomo k(100, 200, 300); // 親(Oya1)のコンストラクタのための引数
137
138 std::cout << "子供\n";
139 // Oya1から継承した部分
140 std::cout << " Oya1から継承した関数を利用\n";
141 k.output1(0); // Oya1から継承した priv1 の出力
142 k.output1(1); // Oya1から継承した prot1 の出力
143 k.output1(2); // Oya1から継承した pub1 の出力
144 std::cout << " Kodomoの関数を利用\n";
145 k.output_k(0); // Oya1から継承した priv1 の出力(アクセスできない)
146 k.output_k(1); // Oya1から継承した prot1 の出力
147 k.output_k(2); // Oya1から継承した pub1 の出力
148 std::cout << " (from main) priv1 ? prot1 ? pub1 " << k.pub1 << std::endl;
// pub1 はパブリック部分に継承されるためmainからアクセスできる
149 // Oya2から継承した部分
150 std::cout << " Oya2から継承した関数を利用\n";
151 k.set(0, 500);
152 k.set(1, 600);
153 k.set(2, 700);
154 k.output2(0); // Oya2から継承した priv2 の出力
155 k.output2(1); // Oya2から継承した pub2_1 の出力
156 k.output2(2); // Oya2から継承した pub2_2 の出力
157 std::cout << " Kodomoの関数を利用\n";
158 k.output_k(3); // Oya2から継承した priv2 の出力(アクセスできない)
159 k.output_k(4); // Oya2から継承した pub2_1 の出力
160 k.output_k(5); // Oya2から継承した pub2_2 の出力
161 std::cout << " (from main) priv2 ? pub2_1 " << k.pub2_1 << " pub2_2 ?" << std::endl;
// pub2_1 はパブリック部分に移動されたためmainからアクセスできる
162
163 return 0;
164 }
親1
priv1 10
prot1 20
pub1 30
(from main) priv1 ? prot1 ? pub1 30
親2
priv2 50
pub2_1 60
pub2_2 70
(from main) priv2 ? pub2_1 60 pub2_2 70
子供
Oya1から継承した関数を利用
priv1 100
prot1 200
pub1 300
Kodomoの関数を利用
priv1 ?
prot1 200
pub1 300
(from main) priv1 ? prot1 ? pub1 300
Oya2から継承した関数を利用
priv2 500
pub2_1 600
pub2_2 700
Kodomoの関数を利用
priv2 ?
pub2_1 600
pub2_2 700
(from main) priv2 ? pub2_1 600 pub2_2 ?
#include <iostream>
using namespace std;
class Base1 {
public:
int x;
Base1() {}
Base1(int x1) { x = x1; }
};
class Base2 {
public:
double y;
Base2() {}
Base2(double y1) { y = y1; }
};
class Test : public Base1, public Base2 {
public:
using Base1::Base1;
using Base2::Base2; // 下に示したコンストラクタのため,
// Base2 のコンストラクタは利用されない
// 従って,この行は必要ない
Test(double y1) : Base1(10) {
y = 10.0 * y1;
}
};
int main()
{
Test t1(1); // 継承した Base1 のコンストラクタを利用
cout << "t1.x: " << t1.x << ", t1.y: 未設定\n";
Test t2(3.14); // Test で定義されたコンストラクタを利用
cout << "t2.x: " << t2.x << ", t2.y: " << t2.y << endl;
return 0;
}
t1.x: 1, t1.y: 未設定 t2.x: 10, t2.y: 31.4
/********************************/
/* 派生クラス(フレームの表現) */
/* coded by Y.Suganuma */
/********************************/
#include <stdio.h>
/**********************/
/* クラスAnimalの定義 */
/**********************/
class Animal { /* 動物フレーム */
protected:
int ani; // 生物:0,その他:1
int ox; // 酸素呼吸:0,その他:1
public:
Animal(int k1, int k2) // コンストラクタ
{
ani = k1;
ox = k2;
}
void shu(int sw) // 生物か否かに答える
{
if (ani == sw)
printf("yes\n");
else
printf("no\n");
}
};
/*********************/
/* クラスHumanの定義 */
/*********************/
class Human : public Animal { /* 人間フレーム,クラスAnimalを継承 */
protected:
int height; // 身長
double weight; // 体重
public:
Human(int x, int y) : Animal(x, y) {} // コンストラクタ
void taiju() // 体重を返す関数
{
printf("体重は %f Kgです\n", weight);
}
};
/********************/
/* クラスTaroの定義 */
/********************/
class Taro : public Human { /* 太郎フレーム,クラスHumanを継承 */
public:
Taro(int hei = 0, double wei = 0.0) : Human(0, 0) // コンストラクタ
{
height = (hei == 0) ? 170 : hei;
weight = (wei == 0.0) ? 0.9 * (height - 100) : wei;
}
};
/************/
/* main関数 */
/************/
int main()
{
Human h1(0, 0);
Taro t1(175);
h1.shu(1); // 人間は生物ではない?
t1.shu(0); // 太郎は生物?
t1.taiju(); // 太郎の体重は?
return 0;
}
no yes 体重は 67.500000 Kgです
01 /****************************/
02 /* 仮想関数 */
03 /* coded by Y.Suganuma */
04 /****************************/
05 #include <stdio.h>
06
07 /****************/
08 /* 動物フレーム */
09 /****************/
10 class Animal {
11 public:
12 void print() // 出力
13 // virtual void print() // 出力,仮想関数
14 {
15 printf("動物\n");
16 printf(" 動物は生物である\n");
17 printf(" 動物は酸素呼吸する\n");
18 }
19 };
20
21 /****************/
22 /* 人間フレーム */
23 /****************/
24 class Human : public Animal {
25 public:
26 void print() // 出力
27 {
28 printf("人間\n");
29 printf(" 人間は動物である\n");
30 printf(" 身長は普通170㎝である\n");
31 printf(" 体重は,一般的に,(身長-100)x 0.9で算出される\n");
32 }
33 };
34
35 /****************/
36 /* 太郎フレーム */
37/****************/
38 class Taro : public Human {
39 public:
40 void print() // 出力
41 {
42 printf("太郎\n");
43 printf(" 太郎は人間である\n");
44 printf(" 太郎の身長は175㎝である\n");
45 }
46 };
47
48 /*************/
49 /* main 関数 */
50 /*************/
51 int main()
52 {
53 Animal a1;
54 Human h1;
55 Taro t1;
56
57 a1.print();
58 h1.print();
59 t1.print();
60
61 Animal *pt[3] = {&a1, &h1, &t1};
62
63 pt[0]->print();
64 pt[1]->print();
65 pt[2]->print();
66
67 return 0;
68 }
動物
動物は生物である
動物は酸素呼吸する
人間
人間は動物である
身長は普通170㎝である
体重は,一般的に,(身長-100)x 0.9で算出される
太郎
太郎は人間である
太郎の身長は175㎝である
動物
動物は生物である
動物は酸素呼吸する
動物
動物は生物である
動物は酸素呼吸する
動物
動物は生物である
動物は酸素呼吸する
動物
動物は生物である
動物は酸素呼吸する
人間
人間は動物である
身長は普通170㎝である
体重は,一般的に,(身長-100)x 0.9で算出される
太郎
太郎は人間である
太郎の身長は175㎝である
動物
動物は生物である
動物は酸素呼吸する
人間
人間は動物である
身長は普通170㎝である
体重は,一般的に,(身長-100)x 0.9で算出される
太郎
太郎は人間である
太郎の身長は175㎝である
#include <iostream>
using namespace std;
class Base {
//class Base final { 派生クラスを生成できない
public:
Base() {}
virtual void f_final() final { cout << "Base_final\n"; }
virtual void f_over() { cout << "Base_over\n"; }
void f_norm() { cout << "Base_norm\n"; }
};
class Test : public Base {
public:
Test() {}
// void f_final() override { cout << "Test_final\n"; } エラー
void f_over() override { cout << "Test_over\n"; }
// void f_norm() override { cout << "Test_norm\n"; } エラー
void f_norm() { cout << "Test_norm\n"; }
};
int main()
{
Base b;
cout << "Base: Base の f_final を使用 ";
b.f_final();
cout << "Base: Base の f_over を使用 ";
b.f_over();
cout << "Base: Base の f_norm を使用 ";
b.f_norm();
Test t;
cout << "Test: Base の f_final を使用 ";
t.f_final();
cout << "Test: Test の f_over を使用 ";
t.f_over();
cout << "Test: Test の f_norm を使用 ";
t.f_norm();
return 0;
}
Base: Base の f_final を使用 Base_final Base: Base の f_over を使用 Base_over Base: Base の f_norm を使用 Base_norm Test: Base の f_final を使用 Base_final Test: Test の f_over を使用 Test_over Test: Test の f_norm を使用 Test_norm
/****************************/
/* 抽象クラス */
/* 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];
}
}
// データの入力
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) {
int 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;
}
}
}
}
for (int i1 = 0; i1 < n; i1++)
delete [] p[i1];
delete [] p;
delete [] m;
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)
{
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;
double pi = 4.0 * atan2(1.0, 1.0);
if (t3 > pi)
t3 -= 2.0 * pi;
else {
if (t3 < -pi)
t3 += 2.0 * pi;
}
int sw;
if (t3 > 0.0)
sw = 1;
else
sw = 0;
return sw;
}
/************************************************/
/* 三角形内に他の頂点が存在するか否かのチェック */
/* n : 点の数 */
/* k : 開始点番号 */
/* m : 点番号 */
/* p : 点の座標 */
/* return : =0 : 存在しない */
/* =1 : 存在する */
/************************************************/
int Polygon::check2(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 (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);
double pi = 4.0 * atan2(1.0, 1.0);
int sw = 0;
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];
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()
{
// Figure f1; エラー,抽象クラスからオブジェクトの生成はできない
/*
楕円
*/
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;
}
楕円の長径は? 5
楕円の短径は? 2
与えられた楕円の面積は 31.4159 です
点の数は? 3
各点の座標の入力(反時計回り)
1 番目の点のx座標は? 0
1 番目の点のy座標は? 0
2 番目の点のx座標は? 2
2 番目の点のy座標は? 0
3 番目の点のx座標は? 1
3 番目の点のy座標は? 2
与えられた多角形の面積は 2 です
| 情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |