継承の基本

  この例は,クラス Kodomo が 2 つの親 Oya1 と Oya2 を継承している例です.78 行目の定義において,Oya1 に対しては public を宣言しているため,Oya1 の public メンバーはそのまま Kodomo の public メンバーに継承されます.しかし,Oya2 に対しては何も宣言していないため,すべてのメンバーが,Kodomo の private メンバーに継承されます.しかし,106 から 108 行目の宣言により,pub2_1,set,および,output2 は,Kodomo の public メンバーに継承されます.

  クラス Kodomo 自体は,コンストラクタを必要としませんが,Oya1 が必要とするため,81 行目の宣言により,Oya1 のコンストラクタにパラメータを引き渡しています.

  親の public および private なメンバーがどのようにして子供に継承されるのかを,プログラムとその出力結果を見て十分理解してください.

001	/****************************/
002	/* 派生クラス               */
003	/*      coded by Y.Suganuma */
004	/****************************/
005	#include <iostream>
006	
007	/********************/
008	/* クラスOya1の定義 */
009	/********************/
010	class Oya1 {
011			int priv1;
012		protected:
013			int prot1;
014		public:
015			int pub1;
016			Oya1 (int n1, int n2, int n3)   // コンストラクタ
017			{
018				priv1 = n1;
019				prot1 = n2;
020				pub1  = n3;
021			}
022			void output1(int sw)   // 出力
023			{
024				switch (sw) {
025					case 0:
026						std::cout << "   priv1 " << priv1 << std::endl;
027						break;
028					case 1:
029						std::cout << "   prot1 " << prot1 << std::endl;
030						break;
031					case 2:
032						std::cout << "   pub1 " << pub1 << std::endl;
033						break;
034				}
035			}
036	};
037	
038	/********************/
039	/* クラスOya2の定義 */
040	/********************/
041	class Oya2 {
042			int priv2;
043		public:
044			int pub2_1, pub2_2;
045			void set(int sw, int n)   // 値の設定
046			{
047				switch (sw) {
048					case 0:
049						priv2 = n;
050						break;
051					case 1:
052						pub2_1 = n;
053						break;
054					case 2:
055						pub2_2 = n;
056						break;
057				}
058			}
059			void output2(int sw)   // 出力
060			{
061				switch (sw) {
062					case 0:
063						std::cout << "   priv2 " << priv2 << std::endl;
064						break;
065					case 1:
066						std::cout << "   pub2_1 " << pub2_1 << std::endl;
067						break;
068					case 2:
069						std::cout << "   pub2_2 " << pub2_2 << std::endl;
070	 					break;
071				}
072			}
073	};
074	
075	/**********************/
076	/* クラスkodomoの定義 */
077	/**********************/
078	class Kodomo : public Oya1, Oya2 {
079		public:
080						// コンストラクタ(基底クラスのコンストラクタのために必要)
081			Kodomo (int n1, int n2, int n3) : Oya1(n1, n2, n3) {}
082			void output_k(int sw)   // 出力
083			{
084				switch (sw) {
085					case 0:   // 親のprivate変数にはアクセスできない
086						std::cout << "   priv1 ?" << std::endl;
087						break;
088					case 1:
089						std::cout << "   prot1 " << prot1 << std::endl;
090						break;
091					case 2:
092						std::cout << "   pub1 " << pub1 << std::endl;
093						break;
094					case 3:   // 親のprivate変数にはアクセスできない
095						std::cout << "   priv2 ?" << std::endl;
096						break;
097					case 4:
098						std::cout << "   pub2_1 " << pub2_1 << std::endl;
099						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  ?