前回は、次のようなソースコードをご覧いただきました。
#include <iostream>
int main()
{
const std::string ch0 = "Typical: I don't know anything about programming!\n";
const std::string ch ("Simplified form: I don't know anything about programming!\n");
const std::string* ch1 = new std::string ("Pointer form: I don't know anything about programming!\n");
std::cout << "Popular: I don't know anything about programming!" << std::endl;
printf(ch0.c_str());
std::cout << ch.data();
std::cout << ch1->data();
std::cout << ch.c_str();
std::cout << ch1->c_str();
std::cout.write(ch.c_str(), ch.size());
std::cout.write(ch1->c_str(), ch1->size());
delete ch1;
return int(0);
}
このソースコードを見た人は、次のような印象の、いずれかをお持ちになっていると想像されます。
印象1:とにかく難しい!
印象2:Cのソースコードとどこか似ている
印象3:#includeに続くiosteamという意味が分からない
印象4:stdio.hがないにもかかわらず、printf関数が呼び出されていることが不思議だ!
印象5:std::coutのstdの意味が分からない
印象6:std::coutの「::」の意味が分からない
印象7:std::coutのcoutの意味が分からない
印象8:「<<」の意味が分からない
印象9:std::endlのendlの意味が分からない
印象10:「std::string ch」のstringの意味が分からない
印象11:「std::string ch」のchの意味が分からない
印象12:ch.data()の意味が分からない
印象13:ch.c_str()の意味が分からない
印象14:std::cout.writeの意味が分からない
印象15:ch.size()の意味が分からない
印象16:std::string*の「*」の意味が分からない
印象17:std::string* ch1の「ch1」の意味が分からない
印象18:ch1->data()の意味が分からない
印象19:ch1->c_str()の意味が分からない
印象20:ch1->size()の意味が分からない
今回からは、このリストを構成する個々の項目の意味と背景をじっくり考えることにします。それではさっそく、第1項目である「印象1:とにかく難しい!」の意味と背景を考えてみましょう。
紹介されたコードを見てなぜ難しく感じるのでしょうか。端的に言ってしまえば、このソースコードはきわめて単純なものではあっても、最近のソフトウェア開発技術を根底から支える概念をすべて含んでいるからです。プログラミング経験の少ない方や、これからプログラミング技術を学習しようとしている人が、"分からない!"、あるいは、"とにかく難しい!"という声をあげても、何の不思議もありません。関数、インクルードファイル、クラス、オブジェクト、ポインタ、あるいは、メソッドなどのソフトウェア概念が何気なく使われています。
たとえば、皆さんの多くは、「インクルードファイル」という言葉をご存知かと思います。Cの世界では、「stdio.h」というファイルはインクルードファイルの典型的なものです。一方、C++の世界では、上に紹介しているソースコードでも使用されている「iostream」が典型的なインクルードファイルと言われています。ところが皆さん、これらインクルードファイルの表現方法は、CとC++の2つの世界では異なっています。なぜ異なっているのでしょうか。筆者は残念がらその理由を正確に承知していませんが、次の点ははっきりしています。
・Cは国際標準プログラミング言語である。
・プログラミング言語Cの言語仕様は国際標準プログラミング言語Cの標準化委員会が決めている。
・C++は国際標準プログラミング言語である。
・プログラミング言語C++の言語仕様は国際標準プログラミング言語C++の標準化委員会が決めている。
インクルードファイル「stdio.h」は拡張子「.h」を持っているため、「ヘッダファイル」とも呼ばれています。それでは、拡張子「.h」を持たない「iostream」ファイルはなんと呼べばよいのでしょうか。おそらく、多くの開発者は、慣例的に、ヘッダファイルと呼んでいると思います。C++標準化委員会はなぜ拡張子「.h」を外したのでしょうか。さらにいえば、C標準化委員会とC++標準化委員会の間の連携はどうなっているのでしょうか。C標準化委員会は、拡張子「.h」を外したC++標準化委員会の決定に異議を挟まなかったのでしょうか。
C++設計者のBjarne Stroustrup氏のいくつかの論文を読んでみると、2つの委員会は相互に独立しており、それほどの交流がなかったようです。また、本「IT談話館」のこの記事に目を通すと分かりますが、C標準化委員会は独特の雰囲気を持っていたようです。C言語設計者のDennis Ritchie氏は、"委員会参加者からたびたびプレッシャをかけられた"、"私は委員会に出席していない"などと繰り返し発言しています。Stroustrup氏は、分かりにくい言語機能に関して、"それは歴史的な事故"という表現をよく使います。"分かりにくい言語機能"は、おそらく、"特定の委員のプレッシャにより誕生したものであり、それは歴史的な事故である"と(暗に)批判しているのではないかと思います。
上に紹介したソースコードを見て、"分からない!"、あるいは、"とにかく難しい!"と感じることは、自然なことではないかと筆者は思います。C++標準化委員会の参加メンバのほとんどは、コンパイラライタといわれます。すると、それより古い歴史を持つC標準化委員会の参加メンバはいったいどのような方々だったのでしょうか。おそらく、電気や電子回路の専門家、あるいは、OSの開発者などだったのでしょう。そして、筆者は想像します。そのようなC標準化委員会の参加メンバが"分かりやすいプログラミング言語仕様を作成することはできなかったはずだ!"、と。
本「IT談話館」のこの連載におけるDennis Ritchie氏の発言内容をじっくり読んでみてください。同氏は物理学への限りない情熱を持っていることを告白する一方、「人のために何かを分かりやすく説明する」という姿勢はほとんど見せていません。この人が匙を投げるほどのメンバがC標準化委員会には参加していたわけです。そのようなメンバたち(悪い言葉で言えば、技術オタク)が世間に提出する仕様書の文章レベルは押して知るべし!、ではないでしょうか。ちなみに、Stroustrup氏は、(筆者の知る限り)C標準化委員会に好感を持っていません。
ところで皆さん、比較的新しいプログラミング言語であるJavaやC#はヘッダファイルという概念を持っていますか。持っていませんね。なぜ持っていないのでしょう。理由は簡単です。そのような"得体の知れない、難しい"概念を持っていなくとも、ソフトウェアを開発することができるからです。JavaやC#はヘッダファイルという概念を捨てたのではなく、"ヘッダファイルとは何か"を問い直し、その本質的な意味と便利さを理解した上で、「より分かりやすい概念(パッケージと名前空間)に進化させた」のです。