情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |
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 です
情報学部 | 菅沼ホーム | 全体目次 | 演習解答例 | 付録 | 索引 |