「オブジェクトポインタ,newとdelete」の編集履歴(バックアップ)一覧に戻る

オブジェクトポインタ,newとdelete - (2012/12/09 (日) 20:05:17) のソース

*オブジェクトポインタとは
※こちらも参照 [[オブジェクト]]
通常のポインタと同様、クラスに対してもポインタで扱うことができる。

クラス型のポインタpはobjを指すようになる。
 Person obj;
 Person *p = &obj;
ポインタの場合、各変数や関数にアクセスする時は
下の例のように->(アロー演算子)を使用する。
 p->age;
 p->selfIntroduction();



*メモリの動的確保と解放(malloc & free、 new & delete)

**new 演算子
C、C++の配列は動的な配列の確保ができない。
new演算子を使うとメモリの動的確保が可能になる。
new,deleteはC++ の演算子なのでincludeの必要はない。
cの<stdlib.h>にあるmalloc と freeでも使用可能
ただし、演算子オーバーロードが使えない、コンストラクタ、デストラクタが呼び出せないため、C++ではnew と deleteを使う。


例:
 double a[10];	// 静的な確保はOK
 
 int n;
 cin >> n;	// キーボードから入力
 double b[n];	// NG コンパイルエラーになる



 mallocの詳細
形式:   #include <stdlib.h>
 
void *malloc(size_t size);

機能:   大きさsizeのメモリ領域を確保する。
引数:   size: 確保したいメモリのバイトサイズ。
返却値: 成功した時:確保したメモリブロックを示すポインタ
失敗した時:NULL


例1:mallocによる動的確保とfreeによる領域解放
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void) {
         int *ip;        /* 割り振られた領域のアドレスを格納するためのint型のポインタipを宣言 */
         int n;

         /* 確保する要素数を入力 */
         cout << "要素数を入力してください: " <<endl;
         cin >> n;

         ip = (int *)malloc(n * sizeof(int));  /* メモリ領域の確保 */

         for (int i=0; i < n; i++){
                  ip[i] = i;
	 }
         for (int i=0;i < n; i++)
                 cout<< ip[i] << endl;
         free(ip);       /* 確保したメモリ領域の解放 */

         return 0;

}
</pre>
}}

例2:newによる動的確保とdeleteによる領域確保

#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void){
	int n;
	cin >> n;
	int * b = new int[n];	// b を確保
	for(int i=0; i < n; i++){
		b[i]=i;
	}
	for(int i=0; i < n; i++){
		cout<< b[i] << endl;
	}
	delete[] b;			// b を解放
        return 0;	
}
</pre>
}}


*二次元配列の場合の動的確保
通常の二次元配列(b[][])だと動的確保ができないので、ポインタ配列を使って擬似的に作り出します。
以下がソースコードです。
#html2(){{
<pre class="brush: cpp;">
#include < iostream >
using namespace std;
int main(void){
	int n,m;
	cin >> n;
	cin >> m;

	//二次元の時はダブルポインタ(** a)を使用
	double ** a = new double*[n];	//n個のポインタ型のdouble型配列確保
	for( int i=0; i < n; i++ ) {
  		  a[i] = new double[m];	//一つ前で作った要素数nの配列をm個確保
	}
	
	for(int i=0; i < n; i++){
		for(int j=0; j < m; j++){
			a[i][j]=j;
		}
	}
	for(int i=0; i < n; i++){
		for(int j=0; j < m; j++){
			cout<<a[i][j]<<endl;
		}
	}
	
	
	for( int i=0; i < n; i++ ) {
   		 delete[] a[i];		//deleteで開放。 
	}
	delete[] a;	//deleteで開放
        return 0;
}
</pre>
}}


*クラスのオブジェクトの動的確保について
※クラスのオブジェクトの場合、標準入力からのオブジェクトの動的確保はできません。
動的確保ができないので、set関数を使ってnewした後に値を与えます。

**Person.h
#html2(){{
<pre class="brush: cpp;">
#include < string >
 
using namespace std;
 
class Person{
private:
        string name;
        int age;
        float height;
        float weight;
	int id;		//人を識別するためのID
	static int sum_person;	//Personオブジェクトの総数保存変数
public: 
	Person(void);
	~Person(void);
	void setStatus();	//set関数
        void selfIntroduction();
};
</pre>
}}


**Person.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
int Person::sum_person=0;	//static変数
//デフォルトコンストラクタ
Person::Person(void){
	Person::sum_person++;	//総数+1
	this->id=sum_person;	//現在の総数をIDとして代入
}
//デストラクタ
Person::~Person(void){
}

void Person::setStatus(){
	cout<<"ID:"<<this->id<<"のデータを入力します。"<< endl;
	cout<<"名前を入力:"<<endl;
	cin >> this->name;
	cout<<"年齢を入力:"<<endl;
	cin >> this->age;
	cout<<"身長を入力:"<<endl;
	cin >> this->height;
	cout<<"体重を入力:"<<endl;
	cin >> this->weight;
	cout<<"データの入力が完了しました。"<<endl;	
}
void Person::selfIntroduction(){
        cout << "私の名前は" << this->name<<"です。"<<endl;
	cout <<"年齢は"<<this->age<<"歳で、身長は"<<this->height <<"cmで、体重は"<<this->weight << "kgです。" << endl;
}
</pre>
}}

**main.cpp
#html2(){{
<pre class="brush: cpp;">
#include "Person.h"
#include < iostream >
using namespace std;

int main(){
	const int NUM=3;
        Person *p[NUM];
        for(int i=0; i < NUM; i++){
              p[i]=new Person();//Person型オブジェクトpをnum個作成
        }
	for(int i=0; i < NUM; i++){
		p[i]->setStatus();
	}
        for(int i=0; i < NUM; i++){
		p[i]->selfIntroduction();
 	}
        return 0;
}
</pre>
}}

memo
※static変数は、明示的に初期値を与えなかった場合には、自動的に 0 で初期化される。
※インスタンスを生成しなくても、静的メンバ変数だけは存在している。
※静的メンバ変数を宣言した場合、その実体の定義をクラス定義の外側に記述する必要がある。 
 cpp の"include の下あたりに クラス名::変数名=値;で定義する。

*問題
**問題1
HumanとBoxの2つのクラスを作成しmainでオブジェクトを2つ生成せよ。
HumanとBoxは下記の仕様で作成せよ。

 Humanクラス
private
 性質:string型 name
public
 操作:putBall
  返り値:なし 
  引数1 :整数型 num(玉を入れる個数)
  引数2 :Box型 b   (どのBoxに入れるか)
  指定された (Box b) に引数1で指定した(num)個ボールを入れる操作を行う

コンストラクタ
 引数:string name
 引数を使ってnameをセットする。

 Boxクラス
private
 性質:整数型 capacity(容量)
   :整数型 ballnum(持っているボールの個数)
public
 操作:addBall
  返り値:なし
  引数1:整数型 num
  num個持っているボールを持っているボールの個数に加算する。
  容量以上のボールはあふれるように処理し、溢れたことを標準出力でユーザに伝える。

  :dispBallnum
  返り値:なし
  引数:なし
  現在のボール個数を画面に出力する。

コンストラクタ
 引数1 整数型 capacity
 引数2 整数型 ballnum
 引数を使って箱の容量と入っているボール個数の初期値をセットする。

 main
 Human(taro,jiro)とBox(b1,b2)のオブジェクトを2つ生成
 b1:初期値は10,0
 b2:初期値は20,5
 各Boxの現在の個数を標準出力
 taroはb1に玉を10個入れる
 jiroはb2に玉を15個入れる
 各Boxの現在の個数を標準出力
  taroはb2に玉を10個入れる
  jiroはb1に玉を15個入れる
 各Boxの現在の個数を標準出力
 生成したオブジェクトを削除
 プログラム終了


#include(highlight)
目安箱バナー