パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.6.3.6(15)
オブジェクト指向プログラミング

オブジェクト指向プログラミングはオブジェクト指向の考え方を取り入れたプログラミング手法である。

その他の外部情報

本サイトでの解釈

オブジェクトをベースとするプログラミングパラダイム。高性能化するコンピュータに対しプログラミングの人的資源不足が危険視され(ソフトウェア危機)、1980年代にプログラミングの生産効率を高める手段として大きく普及した。

オブジェクト指向プログラミングはオブジェクト表現が構文化されているプログラミング言語(オブジェクト指向プログラミング言語)を用いるのが自然だが、必要条件ではない。例えばウインドウズGUIは対象(例えばデスクトップ上に表示されるアプリケーションウィンドウ)をハンドルと呼ぶ整数値で識別し、ハンドルを第一実引数として自由関数(C言語関数)であるAPIをコールする。対象はまさしくオブジェクトであり、ハンドルはオブジェクトを保持するもの(C++のインスタンス変数的なもの)であり、ここでのAPIはオブジェクトメソッドと見なしうる。すなわちC言語でもオブジェクト指向プログラミングは実現できるわけだが、オブジェクト指向プログラミング言語なら当然ながらはるかに簡便となる。ウィンドウズGUIの例においてもMicrosoft Foundation Class(MFC)やwxWidgetsといったC++で記述されたAPIラッパーライブラリ利用が今や一般的であろう。

このように我々はオブジェクトを安易に語るが、そもそもオブジェクトとは何か。その定義は曖昧でほとんどの場合に誤解を避けられない。我々は最初にプログラミング用語として出会うので、英語圏のプログラマなら背景として共通認識する一般的な意味を不幸にして知らない。

英文法の定義するオブジェクト

いや、我らが世代はプログラミングの前に英文法を学んだ。S(subject)、V(verb)、O(object)を用いればオブジェクトはそのままO(object)、オブジェクトメソッドがV(verb)であろう。S(subject)はソースコードに表現されないが曖昧にアプリケーション、あるいはユーザー、あるいはプログラマとすれば良い。

wxWindow* mainWindow=wxTheApp->GetTopWindow();
mainWindow->Hide();

wxWidgetsライブラリ使用の上記C++コード2行目は「アプリケーション(S)がメインウィンドウ(O)を隠す(V)」と読み解ける。コード上の語順は英文法のSVOでなく、Sが明示されないOVとなる。これをもって日本語の方がオブジェクト指向プログラミング言語を理解しやすいとの主張がかつて存在したことを思い出す。

哲学の定義するオブジェクト

オブジェクトの最も広範で厳密な定義は哲学によるが、それはサイト作成者の理解を超える。ウィキペディア(英語)"Object (philosophy)"から言語リンクでたどり着くのはウィキペディア(日本語)"対象"だが、彼此の記述量差は我々の理解不足をさらに強調する。

以降、哲学的定義のオブジェクトを"対象"として参照し、これまで(そしてこれから)明確に定義せず曖昧な文脈で曖昧に用いてきた(そして用いるであろう)"オブジェクト"とは区別する。

プログラミングにおける対象

プログラミングにおける対象を二つに層別する。

  • プログラミングが扱うもの(対象A)
  • プログラミングを記述するもの(対象B)

対象Aはアプリケーション、デザイン、アルゴリズム、ユーザーインターフェース、入出力、データ格納媒体、記憶領域、記憶領域のアドレス、画像、楽曲、ゲームキャラクター、数値、文字列、配列、等々であるが、これらの多くはプログラミング言語に依存しない。プログラマは主観に基づく判断により対象Aの一部をプログラミング言語の定義するデータに解釈して変数に保持する。ある定義によればオブジェクトは変数に保持される対象Aである。別の定義によればオブジェクトは変数に保持される対象Aのうち組み込みデータ型データなどを除いたものである。オブジェクトの定義は多様でその使用は常に注意を必要とするが、ほとんどにおいてオブジェクトとは対象Aの部分集合をプログラミング言語で記述したものと言える。

対象Bはプログラミング言語の構文そのものであり、C++なら関数(アルゴリズムを記述するもの)、演算子(演算を記述するもの)、変数(データの格納を記述するもの)、構造体(データ構造を記述するもの)、クラス(データの振る舞いを記述するもの)、等々であろう。C++で対象Aと対象Bは交わらないが、動的プログラミング言語なら対象Bの要素は対象Aの要素たり得る。この差は実行時におけるソースコードの存否によるもので、C++を含む多くのコンパイラ言語はコンパイルというステップでソースコードを失うが、動的プログラミング言語は実行時にソースコードを解釈する。以下は動的プログラミング言語Pythonの例で、新たにクラスを生成しそのクラスを戻り値として返す関数を示す。

def CreateNewClass(boy):
if boy:
class new_class:
def GetName(self):
return "Jack"
else:
class new_class:
def GetName(self):
return "Betty"
return new_class
def WhoAreYou(kid):
print(kid.GetName())
WhoAreYou(CreateNewClass(True)())
WhoAreYou(CreateNewClass(False)())

C++でこれは不可能だが、コンパイル時ならテンプレートで似たようなことはできる。あえて誤解を招く表現を用いれば、C++のテンプレートは対象Bをコンパイル時に扱うための構文である。以下はコンパイル時に生成されたクラスを返すメタ関数を示す。

#include <iostream>
template<bool> class CreateNewClass
{
public:
class type;
};
template<> class CreateNewClass<true>::type
{
public:
const char* GetName() const {return "Jack";}
};
template<> class CreateNewClass<false>::type
{
public:
const char* GetName() const {return "Betty";}
};
template<typename T> void WhoAreYou(const T& kid)
{
std::cout<<kid.GetName()<<std::endl;
}
int main()
{
WhoAreYou(CreateNewClass<true>::type{});
WhoAreYou(CreateNewClass<false>::type{});
return 0;
}
覚え書き
なおC++は対象Bをプログラミングで扱えないとしたが、関数だけは関数ポインタまたは関数オブジェクトで変数に保持できる。しかしその実態はポインタまたはクラスから実体化されたインスタンスであり、関数自体を値として変数に保持する(値セマンティクス)ことはできない。

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

C++を含むクラスベースのオブジェクト指向プログラミング言語は、オブジェクトの定義と実体を区別する。C++は前者をクラス、後者をインスタンスと定義するが、これはC++に先行したオブジェクト指向プログラミング言語の用語と異なる。

プログラミング言語 オブジェクト(定義) オブジェクト(実体)
Simula クラス オブジェクト
SmallTalk オブジェクト インスタンス
C++ クラス インスタンス

対象を意識せず、オブジェクトとはクラスで定義されインスタンスとして実体化するものとして単純定義することもできよう。プログラミングではむしろこちらの定義が一般的だが、それはオブジェクト指向プログラミングの目的に照らせば本末転倒であろう。このオブジェクト(クラスとインスタンスの総称)はプログラミング言語の構文であるから、対象をこの構文を用いてプログラミングするという事は、プログラム言語設計者の主観に沿って対象を記述することになる。

C++とオブジェクト

C++プログラミングではオブジェクトをクラスとインスタンスの総称として慣用するが、C++規格は異なる定義をとる。C++17規格ドラフトより引用する(JTC1/SC22/WG21 N4659 4.5/p1)。

The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is created by a definition (6.1), by a new-expression (8.3.4), when implicitly changing the active member of a union (12.3), or when a temporary object is created (7.4, 15.2). An object occupies a region of storage in its period of construction (15.7), throughout its lifetime (6.8), and in its period of destruction (15.7). [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. - end note ] The properties of an object are determined when the object is created. An object can have a name (Clause 6). An object has a storage duration (6.7) which influences its lifetime (6.8). An object has a type (6.9). Some objects are polymorphic (13.3); the implementation generates information associated with each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions (Clause 8) used to access them.

要約すればオブジェクトとは型と寿命をもち記憶領域を占有するデータで関数は含まない。つまり変数に保持できる全てであり、クラスから実体化されるインスタンスに組み込みデータ型データや配列データなどを加えたものとなる。C++プログラミングで"オブジェクト"に巡り合ったとき、以下のいずれであるか多くは文脈で判断しなければならない。

  • 対象
  • C++規格の定義するオブジェクト
  • クラスとインスタンスの総称
覚え書き
"オブジェクト"はプログラミング以外の文脈でも登場するため、さらに注意が必要である。以下に数例を示すが、もちろんこれらはプログラミングにおけるオブジェクトと関係ない。
  • オブジェクトファイル(ソースコードファイルをコンパイルして生成される中間ファイル)
  • ドキュメントオブジェクトモデル(HTML、XML文書アクセスの仕組み)
  • コンポーネントオブジェクトモデル(マイクロソフト提唱のソフトウェア部品インターフェース仕様)
  • 3Dオブジェクト(3Dモデルを構成する立体図形)