情報学部 菅沼ホーム 目次 索引

Java から JavaScript,C++ への変換

      1. Java によるプログラム
      2. JavaScript への変換
      3. C++ への変換

  1. Java によるプログラム

      最初に,Java によるプログラムを挙げておきます.先に述べた時間割作成プログラムとは異なっていますが,その構造等は似たものにしてあります.
    01	import java.io.*;
    02	import java.util.*;
    03				// Data クラス
    04	class Data {
    05		int x;
    06		int y[];
    07		ArrayList <Integer> z;
    08		Data(int k) {
    09			x    = k;
    10			y    = new int [2];
    11			y[0] = k * 20;
    12			y[1] = k * 10;
    13			z    = new ArrayList <Integer> ();
    14			z.add(new Integer(k * 200));
    15			z.add(new Integer(k * 100));
    16		}
    17	}
    18				// Use クラス
    19	class Use {
    20		Data DT;
    21					// コンストラクタ
    22		Use (Data dt) {
    23			DT = dt;
    24		}
    25					// func
    26		void func() {
    27			System.out.println("   **in func in*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z.get(2) + " size_of_z " + DT.z.size());
    28			DT.x    = 3;
    29			DT.y[1] = 30;
    30			DT.z.add(new Integer(400));
    31			System.out.println("   **in func out*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z.get(3) + " size_of_z " + DT.z.size());
    32		}
    33	}
    34	
    35	public class Test {
    36		public static void main(String args[])
    37		{
    38					// Data,Use オブジェクトの生成
    39			Data DT = new Data(1);
    40			Use US  = new Use(DT);
    41			System.out.println("**in main 1*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z.get(1) + " size_of_z " + DT.z.size());
    42					// Data オブジェクトの変更
    43			DT.x    = 2;
    44			DT.y[1] = 20;
    45			DT.z.add(new Integer(300));
    46			System.out.println("**in main 2*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z.get(2) + " size_of_z " + DT.z.size());
    47					// func の呼び出し
    48			US.func();
    49			System.out.println("**in main 3*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z.get(3) + " size_of_z " + DT.z.size());
    50		}
    51	}
    		
    39 行目

      Data クラスのインスタンス(オブジェクト) DT を生成しています.Data クラスは,int 型の変数 x,int 型の配列 y,及び,Integer クラスのオブジェクトを要素とするArrayList クラスのオブジェクト z をそのメンバーとして持っています.これらの変数は,08 行目~ 16 行目に示すコンストラクタによって,以下に示す 41 行目の出力結果のような値で初期設定されます(変数の一部だけを示す,以下同様).
        **in main 1*** x 1 y[1] 10 z 100 size_of_z 2			
    40 行目

      Data クラスのオブジェクト DT を引数として,Use クラスのオブジェクト US を生成しています.DT をクラス Use 内の他のメソッドにおいても使用したいため,22 行目~ 24 行目に示すコンストラクタによって,引数をクラス Use のメンバー DT に代入しています.

    43 行目~ 45 行目

      main メソッド内において,Data クラスのオブジェクト DT 内の値を,以下に示す 46 行目の出力結果のような値に変更しています.
        **in main 2*** x 2 y[1] 20 z 300 size_of_z 3			
    48 行目

      Use クラスのメソッド func ( 26 行目~ 32 行目)を呼んでいます.以下に示す 27 行目の出力結果(変数の一部だけを示す)から明らかなように,43 行目~ 45 行目の main メソッドにおける修正が,Use クラスのオブジェクト内の DT に反映されています.これは,40 行目の宣言によって,Data クラスのオブジェクト DT のアドレスが Use クラスのコンストラクタに渡され,それが,20 行目の変数 DT に代入されているとみなせるからです.つまり,main メソッドにおける DT も,Use クラスのオブジェクト US 内の DT も,同じものであるとみなせるからです.
           **in func in*** x 2 y[1] 20 z 300 size_of_z 3			

      実際,Use クラスのメソッド func 内において,Data クラスのオブジェクト DT 内の値を変更していますが( 28 行目~ 30 行目),その結果は,31 行目の出力結果(下に示す出力結果の 1 行目)に反映されると共に,main メソッド内の 49 行目の出力結果(下に示す出力結果の 2 行目)にも反映されています.
           **in func out*** x 3 y[1] 30 z 400 size_of_z 4
        **in main 3*** x 3 y[1] 30 z 400 size_of_z 4			

  2. JavaScript への変換

      Java Script においては,新しいオブジェクトの生成をクラスのオブジェクトの生成とみなせば,Java とほとんど同じようなプログラムが可能です.35 行目における Use オブジェクトの生成では,Java と同様,DT オブジェクトのアドレスが引数として渡されるものとみなせます.実際,Java の場合と同じ出力結果が得られています.下に示すページを表示して,「 OK 」ボタンをクリックすれば,出力結果を見ることができます.
    01	<!DOCTYPE HTML>
    02	<HTML>
    03	<HEAD>
    04		<TITLE>関数</TITLE>
    05		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    06		<SCRIPT TYPE="text/javascript">
    07			str = "";
    08			US  = null;
    09					// Data オブジェクト
    10			function Data (k) {
    11				this.x    = k;
    12				this.y    = new Array(2);
    13				this.y[0] = k * 20;
    14				this.y[1] = k * 10;
    15				this.z    = new Array();
    16				this.z[0] = k * 200;
    17				this.z[1] = k * 100;
    18			}
    19					// Use オブジェクト
    20			function Use (dt) {
    21				this.DT = dt;
    22			}
    23					// Use オブジェクトのメンバー関数 func
    24			Use.prototype.func = function() {
    25				str = str + "   **in func in*** x " + US.DT.x + " y[1] " + US.DT.y[1] + " z " + US.DT.z[2] + " size_of_z " + US.DT.z.length + "\n";
    26				US.DT.x    = 3;
    27				US.DT.y[1] = 30;
    28				US.DT.z[3] = 400;
    29				str = str + "   **in func out*** x " + US.DT.x + " y[1] " + US.DT.y[1] + " z " + US.DT.z[3] + " size_of_z " + US.DT.z.length + "\n";
    30			}
    31	
    32			function run() {
    33						// Data,Use オブジェクトの生成
    34				var DT = new Data(1);
    35				US     = new Use(DT);
    36				str = str + "**in main 1*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z[1] + " size_of_z " + DT.z.length + "\n";
    37						// Data オブジェクトの変更
    38				DT.x    = 2;
    39				DT.y[1] = 20;
    40				DT.z[2] = 300;
    41				str = str + "**in main 2*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z[2] + " size_of_z " + DT.z.length + "\n";
    42						// func の呼び出し
    43				US.func();
    44				str = str + "**in main 2*** x " + DT.x + " y[1] " + DT.y[1] + " z " + DT.z[3] + " size_of_z " + DT.z.length + "\n";
    45						// 結果の設定
    46				document.getElementById("tx").value = str;
    47			}
    48		</SCRIPT>
    49	</HEAD>
    50	<BODY  STYLE="font-size:130%">
    51		<P STYLE="text-align:center">
    52			<INPUT TYPE="button" VALUE="OK" onClick="run()" STYLE="font-size:90%"><BR><BR>
    53			<TEXTAREA TYPE="text" ID="tx" COLS="50" ROWS="5" STYLE="font-size: 100%"></TEXTAREA>
    54		</P>
    55	</BODY>
    56	</HTML>
    		

  3. C++ への変換

      最初,余り深く考えず,Java のプログラムを以下に示すような形に変換してしまいました.しかし,このプログラムを実行すると,その下に示すような結果が得られ,目的とする結果とは異なってしまいます.ただし,上に示した例と異なり,要素数 2 の通常の配列 w を追加しています.
    01	#include <iostream>
    02	#include <vector>
    03	using namespace std;
    04				// Data クラス
    05	class Data {
    06		public:
    07			int x;
    08			int *y;
    09			int w[2];
    10			vector <int> z;
    11			Data() {}   // 必ず必要
    12			Data(int k) {
    13				x    = k;
    14				y    = new int [2];
    15				y[0] = k * 20;
    16				y[1] = k * 10;
    17				w[0] = 25;
    18				w[1] = 15;
    19				z.push_back(k * 200);
    20				z.push_back(k * 100);
    21			}
    22	};
    23				// Use クラス
    24	class Use {
    25		Data DT;
    26		public:
    27					// コンストラクタ
    28			Use (Data dt) {   // Use (Data &dt)
    29				DT = dt;
    30			}
    31					// func
    32			void func(Data DT) {
    33				cout << "   **in func in*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    34				DT.x    = 3;
    35				DT.y[1] = 30;
    36				DT.w[1] = 35;
    37				DT.z.push_back(400);
    38				cout << "   **in func in*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[3] << " size_of_z " << DT.z.size() << endl;
    39			}
    40	};
    41	
    42	int main()
    43	{
    44				// Data,Use オブジェクトの生成
    45		Data DT(1);
    46		Use US = Use(DT);   // Use US(DT); で良い
    47		cout << "**in main 1*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[1] << " size_of_z " << DT.z.size() << endl;
    48				// Data オブジェクトの変更
    49		DT.x    = 2;
    50		DT.y[1] = 20;
    51		DT.w[1] = 25;
    52		DT.z.push_back(300);
    53		cout << "**in main 2*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    54				// func の呼び出し
    55		US.func(DT);
    56		cout << "**in main 3*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    57	
    58		return 0;
    59	}
    		
    **in main 1*** x 1 y[1] 10 w[1] 15 z 100 size_of_z 2
    **in main 2*** x 2 y[1] 20 w[1] 25 z 300 size_of_z 3
       **in func in*** x 2 y[1] 20 w[1] 25 z 300 size_of_z 3
       **in func in*** x 3 y[1] 30 w[1] 35 z 400 size_of_z 4
    **in main 3*** x 2 y[1] 30 w[1] 25 z 300 size_of_z 3		
      出力結果の 4 行目,5 行目から明らかなように,メンバー関数 func 内で修正した結果が反映されていません.これは,C++ においては,46 行目の宣言によって,オブジェクト DT の内容がコピーされて 28 行目~ 30 行目に示すコンストラクタに渡されます.つまり,45 行目で宣言された DT と 28,29 行目の dt は,値等は同じでも,異なるオブジェクトになるからです.29 行目では,その dt の内容が再びコピーされて,25 行目で宣言されたメンバー変数に代入されます.非常に無駄なことを行っています.このように,main 関数内の DT とクラス Use のメンバー変数 DT は,全く異なるオブジェクトであり,メンバー関数 func 内で DT の値を変更しても,main 関数内の DT はその影響を受けません(逆も同様).

      これは,28 行目のコメントに記載したような参照渡しに変更しても同様です.参照渡しの場合,28 行目の dt は,main 関数における DT の別名となるため,main 関数内の DT と同じものになります.しかし,29 行目の代入文によって,dt の内容がコピーされて DT に代入されるため,結局,main 関数内の DT とクラス Use のメンバー変数 DT は,全く異なるオブジェクトとなってしまいます.

      しかし,y[1] に対する出力結果を見てください.メンバー関数 func 内における修正が,main 関数内の DT に反映されていることが分かると思います.変数 y は,08 行目,14 行目に示すように,new 演算子を使用して確保した領域です.クラスのオブジェクトを関数の引数とする場合や代入を行う場合,その内容がコピーされて,引数として渡され,また,代入が実行されます.しかし,この例における変数 y のようなポインタは,そのポインタに記憶されている値だけがコピーされ,そのポインタが指す場所に対しては特別な処理が行われません.従って,main 関数内の DT とクラス Use のメンバー変数 DT は,全く異なるオブジェクトとなりますが,変数 y が指す場所だけは共通になります.このことを理解して使用するならば特に問題はありませんが,変数 y が指す場所も異なる場所にしたいような場合は,特別な処理が必要になります(「 C/C++ 言語」の「代入と初期化」参照).

      Java や JavaScript の場合と同様,DT のアドレスを利用すれば(以下に示すプログラムの 25 行目,27 行目,45 行目),その下に示すように,目的とする結果を得ることができます.勿論,上に示した変更と共に,32 行目~ 37 行目のように,メンバー変数等を参照する方法を変更する必要があります.
    01	#include <iostream>
    02	#include <vector>
    03	using namespace std;
    04				// Data クラス
    05	class Data {
    06		public:
    07			int x;
    08			int *y;
    09			int w[2];
    10			vector <int> z;
    11			Data(int k) {
    12				x    = k;
    13				y    = new int [2];
    14				y[0] = k * 20;
    15				y[1] = k * 10;
    16				w[0] = 25;
    17				w[1] = 15;
    18				z.push_back(k * 200);
    19				z.push_back(k * 100);
    20			}
    21	};
    22				// Use クラス
    23	class Use {
    24		public:
    25			Data *DT;
    26					// コンストラクタ
    27			Use (Data *dt) {
    28				DT = dt;
    29			}
    30					// func
    31			void func() {
    32				cout << "   **in func in*** x " << DT->x << " y[1] " << DT->y[1] << " w[1] " << DT->w[1] << " z " << DT->z[2] << " size_of_z " << DT->z.size() << endl;
    33				DT->x    = 3;   // (*DT).x = 3; でも可(他も同様)
    34				DT->y[1] = 30;
    35				DT->w[1] = 35;
    36				DT->z.push_back(400);
    37				cout << "   **in func in*** x " << DT->x << " y[1] " << DT->y[1] << " w[1] " << DT->w[1] << " z " << DT->z[3] << " size_of_z " << DT->z.size() << endl;
    38			}
    39	};
    40	
    41	int main()
    42	{
    43				// Data,Use オブジェクトの生成
    44		Data DT(1);
    45		Use US(&DT);
    46		cout << "**in main 1*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[1] << " size_of_z " << DT.z.size() << endl;
    47				// Data オブジェクトの変更
    48		DT.x    = 2;
    49		DT.y[1] = 20;
    50		DT.w[1] = 25;
    51		DT.z.push_back(300);
    52		cout << "**in main 2*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    53				// func の呼び出し
    54		US.func();
    55		cout << "**in main 3*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[3] << " size_of_z " << DT.z.size() << endl;
    56	
    57		return 0;
    58	}
    		
    **in main 1*** x 1 y[1] 10 w[1] 15 z 100 size_of_z 2
    **in main 2*** x 2 y[1] 20 w[1] 25 z 300 size_of_z 3
       **in func in*** x 2 y[1] 20 w[1] 25 z 300 size_of_z 3
       **in func in*** x 3 y[1] 30 w[1] 35 z 400 size_of_z 4
    **in main 3*** x 3 y[1] 30 w[1] 35 z 400 size_of_z 4		
      また,以下に示すように,Use クラスのメンバー関数を呼ぶ際,Data クラスのオブジェクト DT を参照渡しによる引数として加えてやれば( 28 行目,51 行目),メンバーに対する参照方法を変更すること無しに上と同じことを実現できます.
    01	#include <iostream>
    02	#include <vector>
    03	using namespace std;
    04				// Data クラス
    05	class Data {
    06		public:
    07			int x;
    08			int *y;
    09			int w[2];
    10			vector <int> z;
    11			Data(int k) {
    12				x    = k;
    13				y    = new int [2];
    14				y[0] = k * 20;
    15				y[1] = k * 10;
    16				w[0] = 25;
    17				w[1] = 15;
    18				z.push_back(k * 200);
    19				z.push_back(k * 100);
    20			}
    21	};
    22				// Use クラス
    23	class Use {
    24		public:
    25					// コンストラクタ
    26			Use () {}   // この行は,無くても可
    27					// func
    28			void func(Data &DT) {
    29				cout << "   **in func in*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    30				DT.x    = 3;
    31				DT.y[1] = 30;
    32				DT.w[1] = 35;
    33				DT.z.push_back(400);
    34				cout << "   **in func in*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[3] << " size_of_z " << DT.z.size() << endl;
    35			}
    36	};
    37	
    38	int main()
    39	{
    40				// Data,Use オブジェクトの生成
    41		Data DT(1);
    42		Use US;
    43		cout << "**in main 1*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[1] << " size_of_z " << DT.z.size() << endl;
    44				// Data オブジェクトの変更
    45		DT.x    = 2;
    46		DT.y[1] = 20;
    47		DT.w[1] = 25;
    48		DT.z.push_back(300);
    49		cout << "**in main 2*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[2] << " size_of_z " << DT.z.size() << endl;
    50				// func の呼び出し
    51		US.func(DT);
    52		cout << "**in main 3*** x " << DT.x << " y[1] " << DT.y[1] << " w[1] " << DT.w[1] << " z " << DT.z[3] << " size_of_z " << DT.z.size() << endl;
    53	
    54		return 0;
    55	}
    		

情報学部 菅沼ホーム 目次 索引