l VisualC C++ (クラスの予備知識) '97.00.00
l.お知らせ 内容 LINK FILE   HTML Win PC Unix MS-DOS C C++ Mfc Java 
目次.C++言語_ 1 クラス 2 派生クラス 5 演算子のオーバーロード クラス(1)
 準備 3 オブジェクト 6 テンプレート 8 etc クラス(2)
 CC++ 4 フレンド・多重継承 7 メモリ確保・例外処理 未使用
int 型   任意の場所で変数を宣言   cout(表示)   関数のオーバーロード   参照   インライン関数   デフォルトの引数   メモリの確保と解放 

VisualC++ には、C 言語とは異なる特徴的な機能があります。

T int 型とポインタ変数
C 言語   int 型とポインタ変数は2バイト(16ビット)です。
VisualC++  int 型とポインタ変数は4バイト(32ビット)です。

T 任意の場所で変数を宣言
VisualC++ では、任意の場所で変数を宣言できます。
#include <iostream.h> /* 変数の宣言位置 */
int a;
void main()
{ a=1;
  cout << a;
  int b=a+1;
  cout << b;
}

T cout(表示) ( MFC では使いません。)
cout 基数の指定 (何進数で表示するかの指定)
進数変換の結果は Windows95 の電卓(関数モード)を使って確認できます。
cout << dec; // 10進表示を指定します。
cout << 123 << endl; // 123 と表示されます。
cout << 0x10 << endl; // 16進数の 10 が、10進数で 32 と表示されます。
cout << oct; // 8進表示を指定します。
cout << 64 << endl; // 8進数で 100 と表示されます。
cout << hex; // 16進表示を指定します。
cout << 64 << endl; // 16進数で 40 と表示されます。
cout << 1.2 << endl; // 小数は 10進数のまま 1.2 と表示されます。

以下は
#include <iomanip.h>
の記述が必要です。

cout 最小出力桁数の指定(小数点は数えません。)
cout << setw(8) << "ABC"; // 00000ABC と表示されます。
cout.width(4); // 4 桁表示の指定をします。
cout << 34 << endl; // 0034 と表示されます。
cout << 10./3. << endl; // 4 桁以上なので、3.33333 と表示されます。
cout.width(); // 元に戻します。

cout 空桁に表示するキャラクタの指定
cout.fill('*'); // 空桁に * を指定します。
cout << setw(4) << 12 << endl; // **12 と表示されます。
cout.fill(' '); // 空桁をスペースに戻します。

cout 左揃え表示の指定
cout << setw(4) << 12 << endl; // 0012 と表示されます。
cout << setiosflags(ios::left); // 左揃え表示を指定します。
cout << setw(4) << 12 << endl; // 1200と表示されます。
cout << setiosflags(ios::right); // 右揃え表示に戻します。

cout 精度(有効桁数)の指定
cout << setprecision(4); // 精度を 4桁に指定します。
cout << 10./3. << endl; // 3.333 と表示されます。
cout << setprecision(20); // 精度を 20桁に指定します。
cout << 10./3. << endl; // 3.33333333333333(関数の精度以内。)
cout << setprecision(6); // 標準の 6 桁に戻します。
cout 精度を小数部に適用する
cout << setprecision(3); // 精度を 3桁に指定します。
cout << setiosflags(ios::scientific); // 小数部の精度指定とする。
cout << 1234.5678 << endl; // 1234.567 と表示されます。
cout << setprecision(6); // 標準の 6 桁に戻します。
cout 精度を仮数部に適用する
cout << setprecision(3); // 精度を 3桁に指定します。
cout << setiosflags(ios::fixed); // 仮数部の精度指定とする。
cout << 1234.5678 << endl; // 1.23e+4 と表示されます。
cout << setprecision(6); // 標準の 6 桁に戻します。

T 関数のオーバーロード
VisualC++ では引数が異なれば同じ関数名を使用することができます。
void func(char i, char j)
{ cout << i/j; }
void func(int i, int j)
{ cout << i/j; }
void func(double i, double j)
{ cout << i/j; }
上記の関数の呼び出し例を示します。
func(10, 3); // 3 と表示されます。
func(1000, 3); // 333 と表示されます。
func(1000., 3.); // 333.333 と表示されます。
もし char 型の引数を持つ関数しか用意していなければ、128 以上の引数を与えることはできません。
また、double 型の引数を持つ関数しか用意していなければ、必要がなくても小数が表示されます。

T 参照
VisualC++ には、ポインタを変数のように扱える参照が用意されています。
int x; // 変数 x を宣言します。
int &y=x; // 変数 x の参照 y を宣言します。
//     参照 y には変数 x のポインタが代入されます。
y=5; // 参照 y を使って x に代入します。
//     参照 y は変数と同じ書式で使用できます。
y は x の別名であると考えることができます。

しかし関数の引数に参照を使用した場合は、実体がポインタなので変数とは違う働きをします。
次の例は、関数の引数に変数を使った場合と、参照を使った場合の比較です。
void func(int y) // 実引数 x の値を、仮引数 y(変数)にコピーします。
{ y=y+1; } // 仮引数 y を変えても、実引数 x の値は変りません。
void main()
{ int x=10;
func(x); // x の値は 10 のまま。
}
void func(int &y) // 実引数 x のポインタを、仮引数 y(参照)にコピーします。
{ y=y+1; } // 参照 y は x のポインタなので、x は +1 されます。
void main()
{ int x=10;
func(x); // x の値は +1 され、11 になります。
}

関数の返り値の参照
関数の返り値の参照を宣言することもできます。
int y; // グローバル変数を宣言。
int &func() // 関数 func と、その返り値 y の参照を宣言。
{ y=y+y; return y; }
void main()
{ y=5;       // 普通に、変数 y に 5 を代入。
  int z=func(); // 普通に関数を呼び出す。5+5 で y=10 になる。
  func()=30; // 返り値の参照を使って y に 30 を代入。
} // func ()は、変数 y の参照(変数と同じように使えるポインタ)
返り値の参照で代入を行うためにグローバル変数を使用しています。
返り値の参照を使うときは関数の動作が終了するときです。
関数の中で宣言した変数では、関数の終了時には消去されてしまいます。

T インライン関数
関数の呼び出しを行うと、現在の仕事の位置を記録するなど、CPU は余分な仕事をする必要があります。
関数の呼び出しの記述を、関数本体の記述に書き換えて、呼び出しの時間を節約するのがインライン関数です。

呼び出しの記述を関数本体の記述に書き換えるのは、プリプロセッサ(コンパイラの前処理プログラム)が行うので、プログラマは inline と指定するだけです。
inline void func() // インラインの指定をした関数。
{ cout << "AA"; }
void main()
{ finc(); // 関数の呼びだし。
}
このようなソースファイルはコンパイルされる前に、プリプロセッサによって次のように書き直されます。
// 関数 func() は、いらないので消されます。
void main()
{ cout << "AA"; // 関数の内容に置き換えられます。
}

ただし、使用する回数の数だけ関数の定義内容がプログラムの中に書かれますので、何回も関数を使用する場合はプログラムのサイズが大きくなってしまいます。
(起動やコピーの時間が長くかかるプログラムになります。)

T デフォルトの引数
VisualC++ では、関数の引数にデフォルト(既定値)の設定をしておき、関数を呼び出す場合に引数の指定を省略することができます。

引数の合計を返す関数で、2番目以降の引数にデフォルト値を設定した例です。
#include <iostream.h> /* デフォルトの引数 */
int func(int a,int b=2,int c=3) // デフォルトの引数を設定した関数
{ return a+b+c; }               // 引数の合計を返します

void main()
{ cout << func(10,20,30) << endl; // 10+20+30 で、60 と表示されます。>
  cout << func(10,20) << endl; // 10+20+3 で、33 と表示されます。
  cout << func(10) << endl; // 10+2+3 で、15 と表示されます。
//cout << func() << endl; // 1番目の引数にはデフォルト値の設定がありません。
  char q; cin >> q; 
}
関数の呼び出し時の引数の省略は、最後の方から順番に省略でき、前や途中だけを省略して呼び出すことはできません。
デフォルト値の設定をしていない引数は、呼び出し時に値を省略できません。

T メモリの確保と解放

メモリを確保する
char *p; // 確保したメモリの位置を記録するためのポインタ変数
p=new char[20]; // char 型のデータを 20 個格納できるだけのメモリを確保
*(p+0)='A'; // 確保したメモリにデータを格納
int *q=new int; // int 型のデータを 1 個格納できるだけのメモリを確保
*q=123; // 確保したメモリにデータを格納
使用が終ったらメモリを解放します
delete p;
delete q;

多次元配列の場合
確保されたメモリのアドレスが、あらかじめ宣言したポインタ配列に代入されます。
次の例は char t[2][3][4][5] という配列を宣言したのと同等に使用できます。
char (*t) [3][4][5]; // ポインタ変数の配列 t を宣言
t = new char[2][3][4][5]; // 四次元配列を格納するメモリを確保
delete [] t; // 使用が終ったらメモリを解放します
ポインタは、* と共に()で囲んで宣言します。
ポインタは、最高次元(上例では[2])を除いた次元を付けて宣言します。
配列のポインタを代入するためのポインタ配列の宣言方法が、ちょっと変っているような気もします。
最下位の次元(上例では[5])の大きさは、変数を使って指定することもできます。

備考 : 上記のポインタ配列に代入される値 (配列 t[2][3][4][5] と全く同じ)
ポインタ配列  代入されるポインタ
t[0][0][0]  先頭+0*(3*4*5)+0*(4*5)+0*5
t[0][0][1]  先頭+0*(3*4*5)+0*(4*5)+1*5
t[0][0][2]  先頭+0*(3*4*5)+0*(4*5)+2*5
t[0][0][3]  先頭+0*(3*4*5)+0*(4*5)+3*5
t[0][1][0]  先頭+0*(3*4*5)+1*(4*5)+0*5
t[0][1][1]  先頭+0*(3*4*5)+1*(4*5)+1*5
t[0][1][2]  先頭+0*(3*4*5)+1*(4*5)+2*5
t[0][1][3]  先頭+0*(3*4*5)+1*(4*5)+3*5
 
t[0][2][0]  先頭+0*(3*4*5)+2*(4*5)+0*5
t[0][2][1]  先頭+0*(3*4*5)+2*(4*5)+1*5
t[0][2][2]  先頭+0*(3*4*5)+2*(4*5)+2*5
t[0][2][3]  先頭+0*(3*4*5)+2*(4*5)+3*5
t[1][0][0]  先頭+0*(3*4*5)+0*(4*5)+0*5
t[1][0][1]  先頭+1*(3*4*5)+0*(4*5)+1*5
 -- 途中省略 --
t[1][2][3]  先頭+1*(3*4*5)+2*(4*5)+3*5
 参考
t[0]     先頭+0*(3*4*5) のアドレス
t[1]     先頭+1*(3*4*5)
t[0][0]  先頭+0*(3*4*5)+0*(4*5)
t[0][1]  先頭+0*(3*4*5)+1*(4*5)
t[0][2]  先頭+0*(3*4*5)+2*(4*5)
t[1][0]  先頭+1*(3*4*5)+0*(4*5)
t[1][1]  先頭+1*(3*4*5)+1*(4*5)
t[1][2]  先頭+1*(3*4*5)+2*(4*5)
多次元配列の用例
#include <iostream.h> /* メモリ確保 (多次元配列) */
void main()
{ char (*t)      [3][4][5]; // ポインタ変数 t を宣言
  t = new char[2][3][4][5]; // 四次元配列を格納するメモリを確保
  t[0][1][2][0]='A';   // 代入します。
  *(t[0][1][2]+1)='B'; // これも代入
  t[0][1][2][2]='C';
  t[0][1][2][3]='\0';
  cout << &(t[0][1][2][0]) << endl; // ABC と表示されます。
  cout << t[0][1][2] << endl;       // 同じく ABC と表示されます。
  cout << t[0][1][2][0] << endl;    // A と表示されます。
  delete [] t; // 使用が終ったらメモリを解放します
}

malloc の場合と同様に、2×3×4×5=120バイトのメモリを確保しても同じです。
#include <iostream.h> /* メモリ確保 (まとめて確保) */
void main()
{ char (*t); // ポインタ変数 t を宣言
  t = new char (2*3*4*5;) // 120バイトのメモリを確保
  *(t+20+10+0)='A';   // 代入します。
  *(t+20+10+1)='B';
  *(t+20+10+2)='C';
  *(t+20+10+3)='\0';
  cout << (t+30) << endl;
  cout << &t[30] << endl;
  delete t; // 使用が終ったらメモリを解放します
}

備考
プログラムのデータはどこに配置されるかによって三つに分けられます。

他のプログラム (例 MS-DOS)
 
プログラム本体
スタック
 
本体の起動時にメモリが確保されます。
グローバルデータ
本体の終了時にメモリが解放されます。
new でメモリを確保します。
動的に確保されたメモリ
delete でメモリを解放します。
 
1.普通の変数やオブジェクトは、必要に応じて、プログラム内のスタックに格納されます。
その変数を使用する関数が終了する毎に自動的に消去されます。
 ここに格納されるデータは、自動変数と呼ばれます。
2.関数の外側で宣言した、グローバル変数やグローバルオブジェクトは、実行プログラム内の指定の場所に格納されます。
 関数の中で static を付けて宣言した変数やオブジェクトも同様です。
 データを格納する分のメモリは、プログラムの起動時に、プログラム本体とは別に確保されます。
 (プログラムファイルではありませんから、エクスプローラには表示されません。)
3.一時的に使用する大きなデータは、必要に応じて(動的に)メモリを確保して格納します。
 (これもファイルではありませんから、エクスプローラには表示されません。)

T

C++言語  準備  CC++ 1 クラス
 
  mtoga@sannet.ne.jp   登録日 '96. 6.15
URL : http://www.page.sannet.ne.jp/mtoga/index.html