C++ データ抽象

データ抽象とは、外部に重要な情報のみを提供し、背後にある実装の詳細を隠すことです。つまり、必要な情報のみを表現し、詳細は提示しません。

データ抽象は、インターフェースと実装の分離に依存するプログラミング(設計)技術です。

現実の生活の具体例を挙げましょう。テレビを例にすると、電源のオン/オフ、チャンネルの切り替え、音量の調整、外部コンポーネント(スピーカー、ビデオレコーダー、DVDプレーヤーなど)の追加ができますが、その内部の実装詳細はわかりません。つまり、ケーブルを介して信号をどのように受信し、信号をどのように変換し、最終的に画面に表示するのかはわからないのです。

したがって、テレビは内部実装と外部インターフェースを分離していると言えます。内部の実装原理を知らなくても、外部インターフェース(電源ボタン、リモコン、音量コントローラーなど)を直接操作するだけでテレビを操作できます。

さて、本題に戻りましょう。C++プログラミングに関して言えば、C++クラスはデータ抽象を可能にします。クラスは、オブジェクトのデータを操作するための多数のパブリックメソッドを外部に提供します。つまり、外部は実際にはクラスの内部実装を知りません。

例えば、プログラムはsort()関数を呼び出すことができますが、その関数がデータのソートに使用するアルゴリズムを知る必要はありません。実際には、関数のソートの基盤となる実装はライブラリのバージョンによって異なる場合があります。インターフェースが変わらなければ、関数呼び出しは通常通り機能します。

C++では、类を使用して独自の抽象データ型(ADT)を定義します。クラスiostreamのcoutオブジェクトを使用して、標準出力にデータを出力できます。次に示すとおりです:

例

#include <iostream> using namespace std; int main( ) { cout << "Hello C++" <<endl; return 0; }

ここでは、coutがユーザーの画面にテキストを表示する仕組みを理解する必要はありません。パブリックインターフェースを知っていれば十分です。cout の基盤となる実装は自由に変更できます。

アクセスラベルによる抽象化の強制

C++では、アクセスラベルを使用してクラスの抽象インターフェースを定義します。クラスは0個以上のアクセスラベルを含むことができます:

  • パブリックラベルで定義されたメンバーは、プログラムのすべての部分からアクセスできます。型のデータ抽象ビューは、そのパブリックメンバーによって定義されます。
  • プライベートラベルで定義されたメンバーは、クラスを使用するコードからアクセスできません。プライベート部分は、型を使用するコードから実装の詳細を隠します。

アクセスラベルの出現頻度に制限はありません。各アクセスラベルは、その直後のメンバー定義のアクセスレベルを指定します。指定されたアクセスレベルは、次のアクセスラベルに遭遇するか、クラス本体の閉じ中括弧(})に遭遇するまで有効です。

データ抽象の利点

データ抽象には2つの重要な利点があります:

  • クラスの内部は保護されており、意図しないユーザーレベルのエラーによってオブジェクトの状態が損なわれることはありません。
  • クラスの実装は、変化する要件や、ユーザーレベルのコードを変更しないことを求めるバグレポートに対応するため、時間の経過とともに変更されることがあります。

データメンバーがクラスのプライベート部分でのみ定義されている場合、クラスの作成者はデータを自由に変更できます。実装が変更された場合は、クラスのコードをチェックして、その変更がどのような影響を与えるかを確認するだけで済みます。データがパブリックである場合、旧表現形式のデータメンバーに直接アクセスする関数はすべて影響を受ける可能性があります。

データ抽象の例

C++プログラムでは、パブリックメンバーとプライベートメンバーの両方を持つクラスはすべて、データ抽象の例として使用できます。次の例を参照してください:

例

#include <iostream> using namespace std; class Adder{ public: // コンストラクタ Adder(int i = 0) { total = i; } // 外部向けのインターフェース void addNum(int number) { total += number; } // 外部向けのインターフェース int getTotal() { return total; }; private: // 外部から隠されたデータ int total; }; int main( ) { Adder a; a.addNum(10); a.addNum(20); a.addNum(30); cout << "Total " << a.getTotal() <<endl; return 0; }

上記のコードがコンパイルおよび実行されると、次の結果が生成されます:

Total 60

上記のクラスは数値を加算し、合計を返します。パブリックメンバーはaddNumとgetTotal外部向けのインターフェースであり、ユーザーがクラスを使用するにはこれらを知っている必要があります。プライベートメンバーはtotalユーザーが知る必要はありませんが、クラスが正常に機能するために必要なものです。

設計戦略

抽象化はコードをインターフェースと実装に分離します。したがって、コンポーネントを設計するときは、インターフェースを実装から独立させておく必要があります。そうすれば、基盤となる実装を変更しても、インターフェースは変更されません。

この場合、どのプログラムがインターフェースを使用しても、インターフェースは影響を受けません。最新の実装を再コンパイルするだけで済みます。

その他の拡張