まず、今回から少しオブジェクト指向についても触れておきます
というのは 複数画像を描画することや 複数サウンドを鳴らす時には
オブジェクト指向はどうしても避けられなくなってくるからです
処理を理解しやすいように一回コンソールでのプロジェクトに戻ります
(コンソールをなかったことにしてはならない・・・)

オブジェクト指向は概念です

例えば、工場などで製品を製造するときに
設計図を作成しておけば
設計図からいくつでも同じ製品が複製できます

ここで設計図をクラス
製品をオブジェクトといいます

厳密ではありませんが、平たく言うとプログラム上では
変数と関数をセットにする仕組みをクラスと呼びます
(C++・C#・Javaなどのいわゆる高級言語はこの機能を備えています)

ここからはC++の機能であるクラスを使うことになります

クラスの情報に基づいて
オブジェクトを生成(メモリを確保)することを
インスタンス化と呼びます

インスタンス化するには主に4通り方法があります
…名錣諒竸瑤澆燭い吠竸宣言する
通常の配列みたいに変数宣言する
new演算子を使って動的なメモリ確保をする(ヒープ領域)
new[]演算子を使って配列のサイズに動的なメモリ確保をする(ヒープ領域)
(JavaやC#ではインスタンス化するには、い靴使えませんが・・・)

C++では、い諒法でインスタンス化した場合
ヒープ領域という特殊な領域にメモリが確保されます

ヒープ領域は明示的に解放しなければ、
プログラムを終了した後でも他のプログラムが使えない領域として残り続け、
(この現象をメモリリークと言います)
メモリリークを起こしているプログラムを起動するたびに
どんどん使えるメモリが減っていき
最終的にはPC、モバイルなどのシステム全体が落ちることになります

なので、必ず使い終わったら解放する必要があります
解放するためにはまず、確保したヒープ領域へのアドレスを覚えておく必要があります
これには、C言語で習ったポインタを使ってアドレスを覚えておきます
(ポインタはアドレスの変数なので)
そして、具体的に
ヒープ領域のメモリを解放するためにはdelete演算子あるいはdelete[]演算子を使います

プログラムが大きくなってくるとソースコード目視によるメモリリーク箇所の特定が難しくなります
メモリリーク箇所の特定にはメモリリーク検出を参考にしてください

今回使うファイルは次のようになってます。どぞー(-ω-)つ旦
fileinstance.cpp
zipでほしい人はこちら
fileinstance.zip

#define _CRT_SECURE_NO_WARNINGS	// 文字列系の関数の警告を消す
#include <stdio.h>
#include <string.h>

// プレイヤークラスを作ってみる
// クラスには変数と関数をセットにしておける
class Player
{
public:	// ←とりあえず、ここではおまじない 

	// クラスの変数、メンバ変数ともよぶ
	char	Name[256];
	int		HP;
	int		MP;

	// クラスの関数、メンバ関数あるいはメソッドともよぶ
	// インラインで実装
	void Attack(){
		// メンバ関数内ではクラスが持っているメンバ変数に自由にアクセスできる
		printf("%s の攻撃 \n",Name);
	}
	// 宣言のみ
	void Show();
};

// メンバ関数の実装
// クラス名::メンバ関数名で定義を書く
// ::演算子(スコープ)でメンバにアクセス
void Player::Show(){
	printf("%s:HP = %d,MP = %d\n",Name,HP,MP);	
}

int main()
{

	// クラス変数の作成(インスタンス化)にはおおまかに4つの方法がある
	
	// ”當未烹韻頂鄒
	Player player;
	// 配列で複数作成
	Player players[4];
	// new(動的メモリ確保)で1つ作成
	// ポインタで確保したメモリのアドレスを覚えておく
	Player* player_ptr = new Player;
	// new[](動的メモリ確保)で複数作成
	// ポインタで確保したメモリのアドレスを覚えておく
	Player* players_ptr = new Player[4];

	// .演算子(カンマ)でアクセス
	strcpy(player.Name,"勇者");
	player.HP = 100;
	player.MP = 10;
	player.Attack();
	player.Show();

	printf("\n\n");

	// 配列による複製が簡単(クラス化の利点)
	for(int i = 0;i < 4;++i){
		sprintf(players[i].Name,"プレイヤー%d",i + 1);
		players[i].HP = 100;
		players[i].MP = 10;
		players[i].Attack();
		players[i].Show();
	}

	printf("\n\n");

	// ポインタの場合は->演算子(アロー)でアクセス
	strcpy(player_ptr->Name,"戦士");
	player_ptr->HP = 200;
	player_ptr->MP = 0;
	player_ptr->Attack();
	player_ptr->Show();

	printf("\n\n");

	// 動的メモリ配列も普通の配列と同じ
	for(int i = 0;i < 4;++i){
		sprintf(players_ptr[i].Name,"プレイヤー%d",i + 1);
		players_ptr[i].HP = 100;
		players_ptr[i].MP = 10;
		players_ptr[i].Attack();
		players_ptr[i].Show();
	}

	printf("\n\n");

	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 、い瞭暗確保の場合、後片付けしないとプログラム終了しても使わないメモリが解放されずに残り続ける(メモリリーク)
	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
	// でnewした場合、deleteで後片付けしなければならない
	delete player_ptr;
	// いnew[]した場合、delete[]で後片付けしなければならない
	delete[] players_ptr;

	return 0;
}

実行結果は次のようになります
instance.jpg

オブジェクト指向が分かれば複製がものすごく簡単になります

・複数画像を描画する
・サウンドを複数鳴らす
ための前準備となります

前:DirectX講座7回
次:DirectX講座9回

選択肢 投票
(^q^)余裕っしょ 4  
まだだ、まだ終わらんよ・・・ 12  
だが、C++だ・・・ 3  

添付ファイル: fileinstance.jpg 316件 [詳細] fileinstance.zip 225件 [詳細] fileinstance.cpp 294件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-09-30 (土) 20:26:06