一般的に難しいといわれているC++を紹介した記事です。
基本文法や変数、オブジェクトの概念を習得済みの中級者向けの記事です。
今回は、特に習得率の高そうなJavaに置き換えながら、C++でのオブジェクトの扱いについて、注意をしなければいけない点について解説します。
クラスの定義
まずはクラスの定義からです。このクラスを使って話を進めて行きます。
1 2 3 4 5 6 7 8 9 10 11 |
[cpp] #include<stdio.h> // ① using namespace std; // ① class Myclass{ int value; // ② public: // ③ void setValue(int val) { value = val; }; // ④ void printValue(){ printf("%d\n",value); }; // ④ }; [/cpp] |
①Javaでのimportとpackageのようなものです。
②C++のクラス内の定義はデフォルトでprivateです。
③この記述以降はpublicになります。
④C++ではこのような書き方でメンバ関数(メソッド)を定義することはあまりしませんが、Javaの表記に近づけるためにこのような書き方をしています。
main関数
次に、main関数です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[cpp] int main(void){ Myclass m1,m2; // ① m1.setValue(10); // ② m2 = m1; // ③ m1.printValue(); // ④ m2.printValue(); // ④ m1.setValue(30); // ⑤ m1.printValue(); // ⑥ m2.printValue(); // ⑦ return 0; } [/cpp] |
①C++の場合はこの記述だけでオブジェクトが生成されます。
②オブジェクトm1のメンバ変数に10が代入されます。
③Javaではこのような記述をした場合、参照のコピーになりますが、C++ではオブジェクトの内容のコピーになります。
④③の代入の結果、m1,m2ともに10と表示されます。
⑤②と同じく、オブジェクトm1のメンバ変数に30を代入しています。
⑥m1は⑤の結果、30と表示されますが・・・
⑦m2は10と表示されます。これは、m1とm2が別のオブジェクトだからです。
ポインタ
Javaの参照のコピーのような動きにしたい場合はポインタを利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[cpp] int main(void){ Myclass *p1 = new Myclass(); // ①-a Myclass *p2 = new Myclass(); // ①-b p1->setValue(10); // ② p2 = p1; // ③ p1->printValue(); // ④ p2->printValue(); // ④ p1->setValue(30); // ⑤ p1->printValue(); // ⑥ p2->printValue(); // ⑥ return 0; } [/cpp] |
①C++でのインスタンス化の記述方法はいくつかありますが、Javaに近い形にするならこのような形でしょうか。2つのオブジェクトを生成し、それぞれ、p1,p2で扱おうとしています。
②ポインタ変数からメンバ関数(メソッド)を呼び出す際はアロー演算子(->)を使います。
③ここでp2に代入されるのはp1のアドレス情報です。p2も①-aで生成したオブジェクトを扱えるようになりました。
④p1,p2ともに10と表示されます。
⑤p1から30をセットしています。
⑥p1,p2ともに30が表示されます。
これでめでたしめでたし・・・とはいきません。
①-bで生成したオブジェクトはどこへ行ってしまったのでしょうか?
Javaにはメモリの自動開放機能がありますが、C++にはありませんので、メモリ上に残ってしまいます。
今回は短いプログラムで、すぐに終了するので害はありませんが、たとえば24時間動き続けるシステムで、繰り返しこれをやってしまうとどうでしょう。メモリが開放されずにどんどん消費され、システムが停止してしまうかもしれません。
このあたりがC++は難しいと言われている原因の一つだと思います。
他にも、他言語では自動でやってくれることを、C++では自分で書かなければいけないことがあります。しかし、「自分で記述することができる」とも言い換えられます。
細かなメモリ管理をしなければいけないが、細かなメモリ管理をすることができる。C++とはそんな言語なのです。