変数の有効範囲(スコープ)

01	/****************************/
02	/* 変数の有効範囲(スコープ) */
03	/*      coded by Y.Suganuma */
04	/****************************/
05	#include <stdio.h>
06	
07	/*******************/
08	/* クラス Example1 */
09	/*******************/
10	class Example1 {
11			int pri;
12		protected :
13			int pro;
14		public :
15			int pub;
16	
17			Example1() {
18				pub = 1000;
19				pri = 2000;
20				pro = 3000;
21			}
22	
23			void sub1() {
24				printf("sub1 pub %d pri %d pro %d\n", pub, pri, pro);
25			}
26	};
27	
28	/*******************/
29	/* クラス Example2 */
30	/*******************/
31	class Example2 : public Example1 {
32	
33		public :
34	
35			Example2() {}
36	
37			void sub2() {
38				printf("sub2 pub %d pro %d\n", pub, pro);
39	//			printf("sub2 pri %d\n", pri);   // 許されない
40			}
41	};
42	
43	void sub();
44	
45	/****************/
46	/* main program */
47	/****************/
48	int main()
49	{
50				// ブロック
51		int x = 10;
52		if (x > 5) {
53			printf("block x %d\n", x);
54			int x = 15;
55			int y = 20;
56			printf("block x %d\n", x);
57			printf("block y %d\n", y);
58		}
59		sub();
60		printf("x %d\n", x);
61	//	int y = 100;   // この文がなければ,y が未定義
62	//	printf("y %d\n", y);
63		extern int z;
64		printf("z %d\n", z);
65				// クラス
66		Example2 ex = Example2();
67		ex.sub1();
68		ex.sub2();
69		printf("public member( pub ) %d\n", ex.pub);
70	
71		return 0;
72	}
73	
74	int z = 30;
75	
76	/************/
77	/* 関数 sub */
78	/************/
79	void sub()
80	{
81		int x = 40;
82		printf("   sub x %d\n", x);
83		printf("   sub z %d\n", z);
84	}
		
  まず,51 行目において,変数 x が定義され,10 で初期設定されています.この変数 x は,この位置から main 関数が終わる 72 行目まで有効になります.52 ~ 58 行目の if ブロック内の 53 行目において,変数 x の値が出力されていますが,当然,その結果は,51 行目で宣言されたときの値になります.しかし,54 行目において,再び,変数 x が宣言されていますので,この位置から if ブロックの最後である 58 行目までは,ここで宣言された x が有効になります.同様に,55 行目で宣言された変数 y の有効範囲も 58 行目までとなります.実際,60 行目における出力文では,51 行目において宣言された変数 x の値が出力されます.また,61 行目のような型宣言を行わず,62 行目のように変数 y の値を出力しようとすればエラーになってしまいます.

  59 行目において関数 sub を呼んでいます.81 行目では,変数 x を宣言し,82 行目において,その値を出力しています.当然,81 行目の宣言を行わなければ,エラーになってしまいますし,また,81 行目の宣言によって,51 行目で宣言された x の値が影響を受けることはありません( 60 行目の出力文に対応する結果参照).しかし,変数 z は,main 関数内にも,関数 sub 内にも宣言されておらず,すべての関数の外側である 74 行目において宣言されています.このように,関数の外側で宣言された変数をグローバル変数と呼び,すべての関数から参照が可能になります.逆に,変数 x や y のように,あるブロック(関数を含む)内だけで有効な変数を,ローカル変数と呼びます.

  グローバル変数 z が,同じファイル内で,かつ,その変数を参照する前に宣言されていますので,そのまま参照可能ですが( 83 行目),異なるファイルや,参照する場所の後ろで宣言されている場合は,63 行目のような extern 指定が必要になります.以上,51 ~ 64 行目内の出力文(関数 sub 内の出力文を含む)によって,以下に示すような出力が得られます.
block x 10
block x 15
block y 20
   sub x 40
   sub z 30
x 10
z 30		
  次に,クラスに付いて考えてみます.10 ~ 26 行目においてクラス Example1 が定義され,31 ~ 41 行目では,クラス Example1 を継承する形で,クラス Example2 が定義されています.31 行目において,public 指定がしてありますので,クラス Example の各変数や関数のアクセス権は,そのままクラス Example2 に引き継がれます.

  66 行目において,Example2 のインスタンス ex を生成し,67 行目では,クラス Example1 から継承した関数 sub1 を通して,3 つの変数を出力しています.このときは,3 つの変数の値がそのまま出力されます.68 行目では,クラス Example2 に追加された関数 sub2 を通して各変数を出力しています.しかし,この場合は,親クラス Example1 の private メンバー変数 pri を参照することができない点に注意してください.また,69 行目のようなクラスの外側からの参照においては,pubulic メンバー変数 pub だけを参照可能です.なお,private 指定は,同じクラス内の関数だけから,protected 指定は,同じクラス,及び,そのクラスを継承したクラスだけから,また,public 指定は,どこからでも参照可能なことを意味します.以上,66 ~ 69 行目内の出力文(クラスのメンバー関数による出力を含む)によって,以下に示すような出力が得られます.
sub1 pub 1000 pri 2000 pro 3000
sub2 pub 1000 pro 3000
public member( pub ) 1000