クラス
クラスの例
ライブラリー
|
クラスとはクラスは,C++の最も重要な機能です.それは,構造体(C言語では,struct)とよく似ています.構造体を用いると,データを階層的に管理でき,わかりやすいプログラムになります.クラスは,この構造体の機能に加えて,データを操作する関数(メンバー関数)も含ませることができます.このようにデータとそれを操作する関数をひとかたまりにすることが,クラスにより可能になります.そこのとにより,わかりやすくまとまったプログラムを作ることが可能になります. 単純なクラスの例クラスは便利だ最も単純なクラスの定義は,次のようにします. class class_name{ 通常,object_listは,書きません.プログラム中で後から宣言できるからです. クラスの例をリスト1に示します.これは,二次関数(f(x)=ax2+bx+c)の係数を設定して,関数とその導関数の値を計算するクラスの例です.リスト1の007—027がクラスの定義です. 001 #include <iostream> 002 using namespace std; 003 004 //============================================================ 005 // class 006 //============================================================ 007 class func2{ 008 double a, b, c; 009 public: 010 void set(double in_a, double in_b, double in_c); 011 double value(double x); 012 double dvalue(double x); 013 }; 014 015 void func2::set(double in_a, double in_b, double in_c){ 016 a = in_a; 017 b = in_b; 018 c = in_c; 019 } 020 021 double func2::value(double x){ 022 return (a*x+b)*x+c; 023 } 024 025 double func2::dvalue(double x){ 026 return a*x+b; 027 } 028 029 030 //============================================================ 031 // main function 032 //============================================================ 033 int main(){ 034 func2 f; 035 double x=2.3; 036 037 f.set(1.0, 2.0, 3.0); 038 cout << "f(" << x << ") = " << f.value(x) << endl; 039 cout << "df/dx(" << x << ") = " << f.dvalue(x) << endl; 040 041 return 0; 042 } 同じようなことが,C言語を使っても可能です(例:global.c, arg.c).しかも,C言語の方がソースプログラムは短く,一見,優れているように感じるかもしれません.しかし,C言語では,二次関数の係数の渡し方が問題になります.係数をグローバル変数(例:global.c)で渡したり,関数の引数(arg.c)に含めたりします.グローバル変数にすると,複数の二次関数が必要な場合,それに応じた数の変数と関数が必要になります.10個の二次関数が必要な場合,30個の変数と10個の関数が必要!! これはまったくナンセンスです.一方,引数を使うと,そのような問題は無くなります.しかし,引数並びに係数(a, b, c)と変数(x)が同列に並ぶので,プログラムが見苦しくなります.さらに,引数が多くなる分,バグが入り込む余地も増えます.その一方で,C++の場合,関数とデータがひとつのクラス内に記述できますので,C言語での問題点は無くなります.
ここで示した簡単な例から,簡単なプログラムであればC言語の方が,ソースが短くて,優れているかもしれません.しかし,少しプログラムが複雑になると,C++のほうが優れていることが多いです.クラスを使うと,そのオブジェクトに関数と変数が同時にメモリーに記憶されるの便利です.C言語では,関数がプログラムの主な役割を果たす.C++では,クラスを使うことによりその関数の機能を拡張できます. コンストラクター先の例では,オブジェクトを作成した時点で,その機能は決まります.あとで,係数を入れるのは面倒であるとともに,美しくありません.そこで,リスト2のようにすると,オブジェクトの生成と同時に,係数の設定ができます. 001 #include <iostream> 002 using namespace std; 003 004 //============================================================ 005 // class 006 //============================================================ 007 class func2{ 008 double a, b, c; 009 public: 010 func2(double in_a=0, double in_b=0, double in_c=0); 011 double value(double x); 012 double dvalue(double x); 013 }; 014 015 func2::func2(double in_a, double in_b, double in_c){ 016 a = in_a; 017 b = in_b; 018 c = in_c; 019 } 020 021 double func2::value(double x){ 022 return (a*x+b)*x+c; 023 } 024 025 double func2::dvalue(double x){ 026 return a*x+b; 027 } 028 029 030 //============================================================ 031 // main function 032 //============================================================ 033 int main(){ 034 func2 f(1.0, 2.0, 3.0); 035 double x=2.3; 036 037 cout << "f(" << x << ") = " << f.value(x) << endl; 038 cout << "df/dx(" << x << ") = " << f.dvalue(x) << endl; 039 040 return 0; 041 } クラス名と同じ関数名がコンストラクターになります.オブジェクト生成時に,このコンストラクター関数が実行されます.コンストラクターには戻り値がありません.そのため,戻り値の型指定を行いません.さらに,void型の指定も行いません.ここでは,オブジェクト生成時に引数を指定しないと,デフォルトの値(a=0, b=0, c=0)になります. 演算子のオーバーロード先のプログラムで,最もみっともないのは,関数の値を得るために,f.value(x)としているところです.できれば,f(x)としたいところです.C++では,演算子のオーバーロードを使うと,その機能が実現できます.具体的には,リスト3のようにします. 001 #include <iostream> 002 using namespace std; 003 004 //============================================================ 005 // class 006 //============================================================ 007 class func2{ 008 double a, b, c; 009 public: 010 func2(double in_a=0, double in_b=0, double in_c=0); 011 double operator()(double x); 012 double dvalue(double x); 013 }; 014 015 func2::func2(double in_a, double in_b, double in_c){ 016 a = in_a; 017 b = in_b; 018 c = in_c; 019 } 020 021 double func2::operator()(double x){ 022 return (a*x+b)*x+c; 023 } 024 025 double func2::dvalue(double x){ 026 return a*x+b; 027 } 028 029 030 //============================================================ 031 // main function 032 //============================================================ 033 int main(){ 034 func2 f(1.0, 2.0, 3.0); 035 double x=2.3; 036 037 cout << "f(" << x << ") = " << f(x) << endl; 038 cout << "df/dx(" << x << ") = " << f.dvalue(x) << endl; 039 040 return 0; 041 } 演算子のオーバーロードと難しそうな名前がついていますが,実態は極めて単純です.「operator()」が関数名となっていると考えれば,通常の関数と殆ど変わりません.ただし,ドット演算子やアロー演算子を使わずに関数(演算子)が呼び出せます. 導関数 |