クラスについて

ここからはC++の主要な機能であるクラスについて解説していきます。

オブジェクト指向プログラミング

C++は、C言語にクラスの概念を取り入れ、オブジェクト指向プログラミングに対応した言語と言えます。
オブジェクト指向とは、データの管理を「オブジェクト」という概念で行うものです。
オブジェクトとはここでは「特定の機能、情報について関係性のあるデータをまとめたもの」という意味です。

オブジェクト指向は

  • カプセル化(情報の隠蔽)
  • ポリモーフィズム(多様性)
  • 継承

の三つの要件があるとされます。
(定義は人によって微妙に差異があります)

カプセル化

例えば「テレビ」には「電波を受信」し、「映像を映す」機能があり、「電源のオンオフ」や「チャンネルの変更」、「ボリュームの調整」といった操作方法があります。
かなり高度なメカですが、一般人はテレビの内部で具体的にどういうことが行われているのかは知りません。
それでも問題なくテレビを使うことができます。

ユーザーにとってテレビの仕組みの知識は必要なく、それを操作する方法だけ提供されていれば不都合はありません。
知らなくても良い情報はわざわざ外部に公開せず、必要な情報だけ公開するのがカプセル化(情報の隠蔽)です。

単純に公開しないだけではなく、許可している操作以外は受け付けないのもカプセル化の特徴です。
テレビを操作する方法としてリモコンや本体のボタンなどがあらかじめ用意されており、それ以外の方法では操作できないようになっています。
操作方法を限定することで「扱い方を間違えると電波を受信しなくなる」などのトラブルは起こらないようになっています。

カプセルの中に何を入れるのかも重要です。
テレビには「電波を受信」「映像を映す」などの「テレビの機能の実現に必要な機能」を入れます。
このカプセルの名前は「テレビ」がふさわしいでしょう。
この「テレビ」こそがオブジェクトです。

逆に言えば、テレビの機能に関係のないものは「テレビ」オブジェクトの中に含めてはなりません。
テレビオブジェクトの仕事はテレビの機能を実現することだけです。
オブジェクトが独立することによって、テレビ機能が必要ならテレビを買えば良く、エアコン機能が必要ならエアコンを買えば良い、という選択ができます。

もし独立性が十分でないと「テレビを買ったらエアコンのリモコンが付いていた」といったことが起こるかもしれません。
別にテレビにエアコンのリモコンが付いていても困りはしませんが、そのリモコン価格もテレビの価格に反映されています。
この「価格」は、プログラミングではマシンに対する負荷となって表れます。
(ファイル容量、メモリ・CPU使用量など)

最悪なのは、エアコンの動作がテレビに依存している場合です。
エアコン自体には温度調節ボタンが存在せず、テレビの音量ボタンの横にエアコンの温度調節ボタンがくっついていることを想像してください。
温度調節するには強制的にテレビを買わなければならず、非効率どころではありません。

このような事態は「テレビ」と「エアコン」が同時に存在することが前提のプログラムを作っているときに起こり得ます。
こういったプログラムは保守性(バグ修正や機能の追加など)が悪く、またエアコンだけを独立したプログラムとして作り直す場合に、関係のないテレビ側のプログラムにも手を入れなければならなくなります。

ポリモーフィズム(多様性)

テレビのリモコンには「電源」ボタンがあります。
エアコンのリモコンにも「電源」ボタンがあります。
どちらも当然、それぞれの機器の電源をオンオフできます。
同じ「電源」に対する操作でも、結果が異なります。

「違うリモコンを操作しているんだから当たり前だろ」と言われればその通りなのですが、これがポリモーフィズムです。
同じ名前(命令)でも、操作対象が異なれば違う結果となるのが多様性です。

「テレビやエアコンには電源ボタンがある」というのは、どちらも家電という共通点があるからです。
「テレビの電源をオンにして」「エアコンの電源をオンにして」と、具体的に機械名を指定しなくても、「あの機械の電源をオンにして」という命令で、対象が具体的に何であるかを指定せず共通の方法で操作ができます。
抽象的な命令ができるというのはプログラミングにおいては効率的なコードが書けるということにつながります。

継承

先ほど述べたような、テレビの基本的な機能を搭載した製品を作ったとします。
この製品はテレビとして問題なく使えますが、4K高画質対応やネットワーク機能などのさらに高機能な製品の開発を行うとします。
新機能は新たに開発する必要がありますが、電源などの機能はゼロから設計するよりも既製品の設計図をベースにして開発した方が効率的です。
これが継承です。

クラスとは

上述のような要求をプログラミング上で実現するための機能がクラスです。
クラスは、カプセル化、ポリモーフィズム、継承、とオブジェクト指向プログラミングに必要な機能をすべて備えています。

実はポリモーフィズムについては関数のオーバーロードですでに解説しています。
(関数の新機能参照)
同じ名前で異なる機能を実装できるという意味からすれば、これも立派なポリモーフィズムです。
(もちろんこれだけではありません)

また、カプセル化についてはC言語の機能だけでも同じようなことができます。
例えばC言語の標準ライブラリは、内部がどのような実装になっているかを気にすることなく使うことができます。
中身を知らなくても(知る手段が提供されてなくても)「電源ボタンを押せば映る」のと「関数を呼び出せばその機能が使える」のは同じことです。

クラスに関係する機能は非常に多く、また複雑です。
オブジェクト指向プログラミングを正しく理解し、機能を最大限に利用してプログラミングをするのは至難の業です。
人によって認識や流儀が異なることもあり、何が正しいのかは人それぞれです。

とはいえ、全ての機能を使いこなさなくても、実現したいものが作れれば取り合えずはそれで構いません。
高度なことは必要に応じて学習していけば良いのです。