「例外処理」と「const」の仕組みについて理解しよう!
プログラムの処理ができなくなった時に「どのように処理するのか?」を決めていき、エラーメッセージを表示したり、他に実行できる処理があれば「代替処理」を実行したりします。
プログラミングでは、「エラーが出た時」について考えていくことも大事なんですね。
それでは、どのようにプログラムを書けばいいのかを学んでいきたいと思います。
「例外処理」の仕組みと作り方
プログラムを実行した際の「エラーを検知すること」を「捕捉する」と表現するそうなのですが、「エラー」のことを「例外」と言うそうです。
この「例外(エラー)」を「捕捉(検知)」する仕組みについて学んでいきたいと思います。
try ~ catch文
プログラムのエラーを検知するためには、「try ~ catch文」を使うそうなのですが、
try{ // エラーを捕捉する処理を書く }catch(捕捉するエラーを指定する){ // エラーが発生したときの処理を書く、 }
のように書いていきます。
エラーを自分で発生させることもでき、例えば、
throw エラーを表すクラス;
のように書くと、エラーが発生します。
プログラムを作ってみると、
#include <iostream> using namespace std; // エラーを表すクラス class ErrorSample {}; int main() { try { throw ErrorSample(); } catch(ErrorSample) { cout << "error" << endl; } }
のようになりますが、今回は「throw」を利用して自分でエラーを発生させています。
このプログラムを実行すると「catch」でエラーが捕捉されるため、
error
と画面に表示されます。
何か入力処理があったとすると、「入力値が正常な範囲でなければとエラーを出す」といった、「入力値チェック処理」で使うケースなどがあるのかなと思います。
まだあまりプログラムを書いた経験が無いので、どのようなケースで使うのかあまり思い浮かばない・・・
「const」の意味
「メンバ・メンバ関数」を宣言する時などに「const」が付いているものがあるのですが、意味がわからなかったので調べてみました。
まず、クラスの「メンバ」についてですが、メンバの宣言時に「const」キーワードを付けると、「内容が変化しない」という意味を付加することができるそうです。
本当にそうなのかを確かめるためにプログラムを書いて試してみました。
「ヘッダーファイル」は、
#ifndef ___CLASS_Sample #define ___CLASS_Sample #include "Sample.h" class Sample { public: const int num = 1; }; #endif
のように作成し、「Sampleクラス」の「実装ファイル」は、
#include <iostream> #include "Sample.h" using namespace std;
となります・・・まだ何も書くものがありませんね(^^;)
「main」関数を、
#include <iostream> #include "Sample.h" using namespace std; int main() { Sample sm; sm.num = 2; return 0; }
のように作成してみると、
error: assignment of read-only member 'Sample::num'
というメッセージがコンパイル時に表示されます。
一度、値を設定をすると「変更できない」ようにするのが「const」の役割だったんですね。なるほど。
でも、なぜか「メンバ関数」にも「const」が付いているものもあります。
「変更できない関数なのかな?」
と思って調べてみると、「const」のメンバにアクセスする関数に付ける必要があるそうです。
例えば、「main」関数を、
#include <iostream> #include "Sample.h" using namespace std; int main() { const Sample sm; cout << sm.getNum() << endl; return 0; }
のように「Sample」クラスを「const」の指定した変数に入れると、この変数を利用して「Sample」クラスのゲッターが使えなくなってしまいます。
なので、「Sample」クラスの「ヘッダークラス」は、
#ifndef ___CLASS_Sample #define ___CLASS_Sample #include "Sample.h" class Sample { public: const int num = 1; int getNum() const; }; #endif
のように「ゲッター」を「const」指定し、同じく「実装ファイル」についても、
#include <iostream> #include "Sample.h" using namespace std; int Sample::getNum() const { return num; }
のように「const」指定をする必要があります。
どんどん学ぶ内容が複雑になっていきますね・・・
復習をしながらもうちょっと詳しく理解していきたいと思います。