この特集のトップページへ
Chapter 1:オブジェクト指向から見たCOM+

見出し 1.1 C++によるオブジェクト指向プログラミング

 オブジェクト指向プログラミング(Object Oriented Programming)を理解したければ,CからC++で拡張された機能を知ることで,その概要はつかめるはずである。C++では,Cの構造体(struct)が拡張され,メンバ変数(プロパティ)とこれを操作するメンバ関数(メソッド)とを1つの括りとして定義可能なクラス(class)が登場した。これにより,プロパティとメソッドを有機的に結合させてクラスをインスタンス化する――つまりオブジェクトを生成する――ことができるようになったのである。しかも,クラスのメンバには,ほかのクラスからアクセスできるか否かを,private(非公開),protected(限定公開),公開(public)というアクセス制御子で制御することができる。

 たとえば,銀行口座を例にすると,次のようなクラスを実装できるようになる(List 1-1)。メンバ変数としては,口座番号,パスワード,口座残高などが考えられるだろう。これらは通常,クラス以外からはアクセスできないようにprivateとして設定する。そして,口座番号を入力したり,預金・出金・残高照会などを実行するメンバ関数は,ほかのクラスからも利用できるようにpublicとして設定する。このようなモデルを定義すると,メンバ変数とメンバ関数を1つのCAccountオブジェクトとして使用できるため,プログラミングがシンプルになる( List 1-2List 1-3))。

 このように,C++の存在を抜きにオブジェクト指向プログラミングの世界を語ることはできない。ここではまず,C++の機能と併せて,オブジェクト指向プログラミングの概要について説明する。

見出し 1.1.1 クラスの継承
 C++には,Cには存在しない「継承」という機能が搭載されている。継承とは,基礎となる基本クラス(base class)を引き継ぐような派生クラス(derived class)を定義することである(Fig.1-1)。概念的には,あらかじめ定義された基本クラスをもとに,その基本クラスからの差分だけを派生クラスとして定義することだと考えていただきたい。

Fig.1-1 オブジェクト指向における継承
fig.1-1

 この機能により,クラスの修正や変更が生じても,修正点や変更点のみを派生クラスとして実装することで,基本クラスのそのほかの部分はそのまま継承すればすむ。たとえば,ある基本クラスのメソッドを変更する場合,直接その基本クラスのメソッドを変更するのではなく,基本クラスのメソッドを上書き(override)するような派生クラスを実装することで,基本クラスのメンバ関数を継承しつつ,メソッドを更新できる(Fig.1-2)。

Fig.1-2 オブジェクト指向における多態性
fig.1-2

 では,銀行口座をモデリングしたCAccountクラスを基本クラスにして,キャッシュディスペンサのクラスを継承してみよう(List 1-4)。

 口座とキャッシュディスペンサの関係は,Fig.1-3のようになるだろう。CAccountクラスを継承したCCashDispenserクラスの定義では,CCashDispenserクラスのメンバ変数にアクセスするためにprivateというアクセス制御子を使うことができない。このように,派生クラスから基本クラスのメンバ変数にアクセスする場合は,アクセス制御子をprivateからprotectedへと変更する必要がある(List 1-5)。

Fig.1-3 CAccountクラスとCCashDispenserクラスの関係
fig.1-3

 先ほどと同じように,任意の口座番号に対して入金・照会・出金の処理を実行するケースを想定する。List 1-4では,CAccountクラスを継承したCCashDispenserクラスを定義している。派生クラスであっても,利用法は基本クラスとほとんど変わらない(List 1-5)。派生クラスであるCCashDispenserクラスのインスタンスを生成し,生成されたCCashDispenserオブジェクトのインスタンス変数cdを使用して,基本クラスを利用する場合と同じようにプログラミングしている。

 CCashDispenserクラスのPay関数は,基本クラスであるCAccountクラスのPay関数をオーバライドしている(List 1-4の31行目およびList 1-6)。そして,派生クラスのPay関数のなかで,基本クラスからパスワードを照会するCAccount::Input_Password(lUPassword),口座番号を照会するCAccount::Input_Account_number(lUAccount_number),基本クラスのCAccount::Pay(lAmount)という各メンバ関数をそれぞれ呼び出し,基本クラスのメソッドを派生クラスで再利用している。また,基本クラスでは出金と残高照会を切り分けて呼び出していたが,派生クラスではPay関数のなかから呼び出すようにしたため,main()関数の見通しもよくなっている。

 このように,基本クラスでしっかりとクラスを設計しておけば,派生クラスでうまく基本クラスのメソッドを活用することができる。ここで紹介した機能には,「基本クラスの差分を派生クラスとして実装できる」という側面のほかに,「基本クラスのメンバ関数を派生クラスで再利用できる」という側面があることに注目してほしい。

prev Chapter 1 2/8 next