1 of 24

C++講座

2 of 24

もくじ

  • 第1章『基本』� 第一の壁:配列と繰り返し�
  • 第2章『クラス』� 第二の壁:ポインタ�
  • 第3章『継承』� 第三の壁:ポリモーフィズム

3 of 24

第2章『クラス』

第二の壁�ポインタ

4 of 24

クラスの宣言

クラス宣言はふつうヘッダファイルにまとめる

#pragma once

class Pinkri{

public:

int hp;

int mp;

};

ぴんくりクラスの宣言

アクセス修飾子(public)

以降に書いたデータはpublic

(他のオブジェクトからも�参照できるようになる)

int型のhp、mpを宣言

コンパイラ一度しか読まないの呪文�(Visual Studioのみ)

Pinkri型を作れる

HP=?

MP=?

Pinkri

5 of 24

クラスからオブジェクトを作る

ぴんくり型の変数pinを作る

int main(){

Pinkri pin;

pin.hp = 100; // pinのHPは100

pin.mp = 50; // pinのMPは50

}

HP=100

MP=50

pin

6 of 24

オブジェクトの初期化と後処理

class Pinkri{

public:

int hp;

int mp;

Pinkri(int h, int m);

~Pinkri();

};

コンストラクタ(初期化)

初めに呼ばれる関数

HPとMPの初期化をする

デストラクタ(後処理)

終了時に呼ばれる関数

今は何もしないが一応作る

7 of 24

クラスの実装

クラスで宣言した関数の中身は

ふつうソースファイルで実装する

Pinkri::Pinkri(int h, int m){

hp = h;

mp = m;

}

Pinkri::~Pinkri(){

// 何もしない

}

引数(関数f(x)でいうx)

ぴんくりのHP、MPに

それぞれ与えられた

引数の値を代入

8 of 24

クラスの実装

これで初期化が簡単になる

int main(){

Pinkri pin(100, 50);

}

コンストラクタの引数に

100, 50を与えたことで

pin.hp = 100, pin.mp = 50

になった

9 of 24

メンバ関数(メソッド)

class Pinkri{

public:

int hp;

int mp;

Pinkri(int h, int m);

~Pinkri();

void Cure();

};

回復魔法Cure()を追加�MPを5消費して�自分のHPを20回復する

10 of 24

関数の実装

関数の中身をソースファイルで実装する

void Pinkri::Cure(){

if(mp < 5){

std::cout << “MPが足らない!” << endl;

}else{

mp -= 5;

hp += 20;

std::cout << “HPが20回復した!” << endl;

}

}

11 of 24

関数の実装

実際にぴんくりを宣言して呼び出す

int main(){

Pinkri pin();

pin.Cure();

}

関数の呼び出しも

データと同様、変数の後に

「.」を付けて記す

12 of 24

関数の引数と戻り値

引数:関数を実行するときに用いるパラメータ

戻り値:関数の実行結果で返す値

例)y=√x … 引数はx、戻り値はy

int nibai(int x){

int y = x * 2;

return y;

}

引数(int型)の値を

2倍にして返す関数

戻り値の型はint

引数xをもとに

戻り値yを計算し、

yを戻り値とする

13 of 24

関数の引数と戻り値

さっき作った2倍関数を使ってみる例

int main(){

int a = nibai(30);

int b = 50;

int c = nibai(b);

}

int nibai(int x){

int y = x * 2;

return y;

}

aの値:60

bの値:50

cの値:100

14 of 24

ポインタ

コンピュータのデータはメモリに格納される

int main(){

int a = 50;

}

0x100001:

0x100002:

0x100003:50

0x100004:

0x100005:

0x100006:

変数aが宣言されると、コンピュータ(OS)が

自動で未使用のメモリを見つけてくれて、

そこにデータを格納して取り扱っている。

15 of 24

ポインタ

ポインタはメモリのアドレスを格納する変数

int main(){

int a = 50;

int *p = &a;

}

0x100001:

0x100002:

0x100003:50

0x100004:0x100003

0x100005:

0x100006:

変数aのアドレス0x100003の値が

変数pに代入され、ここに格納された

16 of 24

ポインタ

アドレスの値を直接操作することもできる

int main(){

int a = 50;

int *p = &a;

*p = 100;

}

0x100001:

0x100002:

0x100003:100

0x100004:0x100003

0x100005:

0x100006:

変数aのアドレス0x100003の値に

100を代入したから、aの値が変わった

17 of 24

ポインタの記号

int *p;

ポインタ変数pを宣言(int* pでもいい)

&a

aのアドレス

*p

ポインタpの指す値

(宣言時の*とは別物なので注意)

18 of 24

ポインタと配列

配列の正体はポインタである

int main(){

int a[5];

for(int i=0; i<5; i++){

a[i] = i + 1;

}

}

0x100001:1

0x100002:2

0x100003:3

0x100004:4

0x100005:5

0x100006:

19 of 24

ポインタと配列

配列はポインタの処理と同等に扱える

int main(){

int a[5];

for(int i=0; i<5; i++){

*(a + i) = i + 1;

}

}

0x100001:1

0x100002:2

0x100003:3

0x100004:4

0x100005:5

0x100006:

ポインタaにi足した場所にi+1を代入

a[i]と同じ意味

20 of 24

ポインタによる動的確保

普通の変数は固定されているが、

ポインタを使うことにより

「動的な」変数を作ることができる

int main(){

int *p = new int;

*p = 100;

delete p;

}

int型の変数の領域を新しく

作って、アドレスをpに入れる

新しく作られた領域に100を代入

newしたら必ずdelete(開放)

21 of 24

ポインタによる動的確保

プログラム中に常にあるのではなく、

登場したり消えたりするようなものは

ポインタを使った動的確保をするのがよい

例)ロード中にキャラクターをロード

int main(){

Pinkri *pin = new Pinkri(100, 50);

pin->Cure();

delete pin;

}

ぴんくり型のポインタ変数pinに

HP100MP50のぴんくりを生成して

そのアドレスを格納する

ポインタ変数経由でデータに

アクセスする場合は

「.」の代わりに「->」を使う

22 of 24

ポインタによる動的確保

一つのコード中で作ったり消したり…

int main(){

Pinkri *pin = new Pinkri(50, 30);

delete pin;

pin = new Pinkri(80, 0);

delete pin;

pin = new Pinkri(20, 60);

delete pin;

}

newしてないのにdeleteする

ということはしないように

コンストラクタは

newしたときに呼ばれ、

デストラクタは

deleteしたときに呼ばれる

23 of 24

配列の動的確保

動的確保で配列を作ると

要素数をプログラム中で自由に設定できる

int main(){

int *p = new int[5];

for(int i=0; i<5; i++){

p[i] = i + 1;

}

delete[] p;

}

配列をnewした場合は

deleteじゃなくて

delete[]になるのに注意

p[i]は*(p + i)と同じ意味

24 of 24