1. C++とは 1-1. 訳の分からない用語を切る * オブジェクト指向について(悪玉その1) -------------------------------------------------------------------------------- オブジェクト指向なんて言うのは大げさ過ぎる。こんなもんだと思うに限る。 -------------------------------------------------------------------------------- オブジェクト指向の説明で必ず登場するのが『オブジェクトというのは、互いにメッセ− ジを交換しながら協調して、作業を進めるものである』と言われている。これをそのまま 真に受けるとえらい目に合うことになる。本屋には、C++やオブジェクト指向について 書いた本が多く並んでいるが、それらを読めば読む程、迷いの深みに入っていってしまう。 オブジェクトに始まり、メッセ−ジ・パッシング、インヘリタンス等と言った訳の分から ない言葉に踊らされてしまうのである。そして従来の言語とはパラダイムが違う。単にC の機能に"++"したという理解だけでは、C++の強力な機能を引き出すことは出来ない。 やたら修飾語の多い言葉でのたまわれるとC++と言うのは、何かしら凄いことが出来る のでないかと思ってしまうのである。 * メッセ−ジについて(悪玉その2) -------------------------------------------------------------------------------- C++にはメッセ−ジと言う機能は無い。Smalltalk でのお話しである。 -------------------------------------------------------------------------------- この用語程、誤解を招き易い言葉は無いと言える。メッセ−ジを出すとかメッセ−ジを受 けると言った表現がされるのだが、C++ではそんなものは存在しないのだ。単に関数を コ−ルしているだけの事を、オブジェクト指向信奉者によって大仰に言い表わされている だけなのだ。オブジェクト指向の本家 Smalltalk では、 多分その表現が正しいのかも知 れない。しかし、今我々はC++を習得したいのであって、Smalltalk に於けるオブジェ クト指向の概念うんぬんを聞かされる必要はない。『メッセ−ジを出すと、それに応じた 細かな処理はメッセ−ジを受けたオブジェクトが勝手に判断してやってくれる』。こんな 事はC++では有り得ないのだ。細かな処理をやってくれるのは、あくまでもプログラマ がそのようにル−チンを作った結果なのである。デ−タとそれをアクセスする関数をまと めたクラスという一つの枠組みの中で、デ−タを間接的にアクセスしていると、あたかも ブラック・ボックスにメッセ−ジを送っているかの様な気になってくる。C++にメッセ −ジと言うちゃんとした機能がある訳では無いのである。 * クラスについて -------------------------------------------------------------------------------- プログラマは頭の中では、昔からクラスを使っていた。クラスなんて当り前である。 -------------------------------------------------------------------------------- ある程度経験を積んだプログラマなら、クラスというような考え方は、自然と行っている ものなのである。何かの処理をするプログラムを設計する場合、デ−タの種類が幾つ、そ れらのデ−タをアクセスする関数はこれこれと考えるのが普通であろう。従来の言語には、 デ−タと関数を対応つける機構がなかったため、プログラマは関数名を工夫するとか、ド キュメントに示すとかしていた訳である。C++にはそうした機構が用意されていて、ク ラスと呼んでいるに過ぎない。本当は完全に Fig.2 のようなイメ−ジではない。 クラス はデ−タの固まりに適用されると言うよりも、個々のデ−タに適用されるとイメ−ジした 方が適切である。 これらはデ−タを アクセスする関数 デ−タA デ−タB の固まり の固まり A B プログラマが頭の中で意識して プログラムできちんとこうした 区別していた。 枠組みを作ることができる。 Fig.1 従来の場合 Fig.2 クラスを使う場合 * インスタンスについて -------------------------------------------------------------------------------- 実は昔からインスタンスを使っていた。呼び名が無かっただけなのだ。 -------------------------------------------------------------------------------- これも色々に説明されている。クラスからその実体を生成したものをオブジェクトと言い、 そのオブジェクトのことをインスタンスと言うとか。ともかく頭がこんがらがって来そう な説明が多いのだ。ここは、オブジェクトの説明とインスタンス本来の意味を、一度切り 離して理解した方がよい。インスタンスはプログラムをちょっとでも書いたことのある人 なら、誰でもを使っているのだ。変数を定義する際には、必らず変数の型を前に置いてい る。例えば int a,struct A で A b のように。インスタンスと言うのは、 元々何かの型 があって、それの実際のコピ−と言うような意味である。だから例の a や b はりっぱな インスタンスであり、呼び名こそ従来特別に無かったものの、ちゃんと昔からインスタン スはあったのである。 * インヘリタンスについて -------------------------------------------------------------------------------- 派生クラスを作る機能の呼び名である。特に意識する必要は無い。 -------------------------------------------------------------------------------- インヘリタンスはC++のクラス階層の構造を作る重要な機能である。あるクラスで基本 的な機能を実装して置き、このクラスに対して上位のクラスを定義する。上位のクラスに は、下位クラスに無かった機能のみを記述すれば、それで下位クラスの機能も持ったクラ スが実現できる。この機能のことをインヘリタンス(継承)と呼んでいる。また下位クラ スに対して、上位クラスのことを派生クラスと呼んでいる。 * 派生クラスについて -------------------------------------------------------------------------------- うまく使うと便利だが、へたに使うとプログラムがごちゃごちゃになる。 -------------------------------------------------------------------------------- 派生クラスは作ろうと思えば幾らでも出来てしまうので、へたをすると、ちょっとずつ違 ったバ−ジョンが幾つもあるような具合になってしまう。何が基本で、何が特殊か応用か 常に考え、派生元のクラスを設計しなければならない。もう1つの欠点は、差分プログラ ミングであるため、クラスのメンバ関数を知るのに、派生元を遡ってそれぞれのクラスの メンバ関数を見て行かなければならないことである。このため1つのクラスで、使えるメ ンバ関数に何が有るのか非常に分かりにくくなってしまう。この欠点を補うため、クラス ブラウザというクラスの内容を一覧するためのツ−ルがメ−カから出されている。 * 仮想関数について -------------------------------------------------------------------------------- 実際にプログラムを作って、ふんふんと覚えた方が早い。用語は覚えるだけムダである。 -------------------------------------------------------------------------------- 仮想関数にからんで多態性(ポリモルフィズム)、動的結合(レイト・バインディング)、 静的結合(ア−リ−・バインディング)等と言う用語が出て来る。これらの言葉は、言葉 尻りだけで覚える必要はない。こんなことを覚える時間があったら、プログラムを少しで も作る方がよっぽどましである。だいたい動的結合の説明をするのに、必ずコンパイラ− の話を持ち出している。動的結合は、コンパイル時に関数を決定付けずに、プログラム実 行時に決定するので動的であると言うのだ。こんな説明で、そうかと理解できる人がどれ だけいるだろう。大抵のプログラマはコンパイラ−やリンカ−が、内部でどんな動きをし ているかまでは関知していないのが普通だろう。 あえて説明すると、多態性は同じ関数名を定義できること。これには仮想関数うんぬんは、 とりあえず関係ない。動的結合は、同じ関数名を区別するための機能と考えてよい。まだ ここではクラス階層は考慮に入れていない。それでは仮想関数は、多態性をクラス階層間 にまで適用できるようにする機能ということになる。基底クラス、派生クラスで同じ関数 名を定義した場合にきちんと所望するクラスの関数を呼び出す機能である。 * 再度メッセ−ジについて -------------------------------------------------------------------------------- メッセ−ジ通信の絵にだまされるな。あれは嘘である。 -------------------------------------------------------------------------------- よく Fig.3 のような絵が載っている。オブジェクトを表わす丸が描いてあって、 矢印が 色々出ている。この絵をぱっと見ると、オブジェクトは独立したプロセスのように見えて しまう。そしてオブジェクト同士はプロセス間通信でもって、自分の状態を他のオブジェ クトに知らせたり、命令を出しているかのようである。もし、これが本当ならオブジェク ト同士が協調して問題を解決していくという最初の表現にピッタリである。しかし、ただ オブジェクトを生成しただけで、1個のプロセスになるはずがない。そうなのだ。我々は ただのEWSやパソコンを使ってC++しているに過ぎないのだから。 Fig.3 の絵は正確には Fig.4 のように描き直されるべきなのだ。 矢印にはメッセ−ジが 送られる順番をつけておくのが正しい。メッセ−ジが送られて初めて、そのオブジェクト は寝ていたのを起こされ、活動する。メッセ−ジの処理が済むとまた寝てしまうのだ。同 時に複数のオブジェクトが活動していることは、普通有り得ないことである。ここでメッ セ−ジと言う用語をあえて用いた。先にC++にはメッセ−ジの機能はないと公言したが、 絵と矢印でオブジェクトの関係を示すには、『概念』としてメッセ−ジを用いると分かり 易いからである。C++では絵の矢印の実態は、相手先オブジェクトの関数の呼び出しに 過ぎないことを再度断わっておく。 3 ○ → ○ ○ → ○ 1 ↑↓ / ↓ ↑↓ 4/ ↓5 * 2 * 本当はこの様な関数の ○ ← ○ ○ ←6 ○ コ−ルの状態があるか → 7→ どうか自体も疑わしい。 Fig.3 インチキの絵 Fig.4 正しい絵 * もう一度メッセ−ジについて -------------------------------------------------------------------------------- メッセ−ジのやり取りをクライアント・サ−バに喩えるのは、気持ちに過ぎない。 -------------------------------------------------------------------------------- 本当にクライアント・サ−バの機能でもって、メッセ−ジのやり取りをしているなんて思 ったら大間違いである。あくまでも本なんかで言っていることは、オブジェクトの関係に おいて、気持ちとしてクライアントとサ−バだよと説明しているに過ぎないのである。実 際のクライアント・サ−バを実現するプログラムでは、クライアントとサ−バはそれぞれ 独立したプロセスとして記述される。例えばサ−バをプロッタ−を制御するプロセスとす る。クライアントはプロット用のデ−タをサ−バに渡して、出力をお願いするプロセスだ としよう。まずクライアントはサ−バ−に今、暇ですかとお伺いをする。サ−バ−はハイ 暇ですとクライアントに返事する。それではデ−タを送りますので、宜しくお願いします という具合になるわけである。このお伺いしたり、返事をしたりしている所は、まさにメ ッセ−ジのやり取りであり、オブジェクト指向のメッセ−ジ通信に良く概念が似ているの である。 【クライアント側】 【サ−バ−側】(プロッタ−) 暇ですか(1) → ← ハイ暇です(a)、暇ではありません(b) デ−タを送ります(2) → ← プロット出力を開始します(c) ← 出力を終了しました(d) 注:(1)...(d) と言うのはメッセ−ジの内容を表わすものである。直接"暇ですか"なんて メッセ−ジを送れるはずがないので、例えばサ−バ−側では"1" という文字列を、内 部で評価して"暇ですか"というメッセ−ジが来たと判断することになる。 Smalltalkには、 このメッセ−ジを判断する『セレクタ』なるものが用意されている ので、クライアント・サ−バであると言う話だが、ただの関数名に見えてしまうのは 私だけであろうか。 * クラス階層について -------------------------------------------------------------------------------- クラス階層を真剣に考えると頭が禿げる。とりあえず何か決めてしまおう。 -------------------------------------------------------------------------------- あるクラスを元に新しいクラスを定義する、即ちクラスを派生させて行くと、縦と横の拡 がりを持つクラス群ができる。これをクラス階層と言う。クラス階層はよくよく考えると、 かなり難しい問題である。ある機能なり、現象なりをいかに分類して整理するかと言う問 題になる。最初から完璧に分類などできるものではない。とりあえず、何か基本となるク ラスを決めてしまい、後は必要に応じてクラスを追加したらどうか。クラスの関係がおか しいと思ったところで、修正して行けばよい。しかし全っく場当たり的に作ってしまうの では能がない。クラスの派生の仕方には何らかの指針があるはずである。 8章の"クラス 階層の分類"で詳しく考察する。 * オブジェクト指向プログラミングについて -------------------------------------------------------------------------------- ごく自然にプログラミングすると、そのままオブジェクト指向プログラミングになる。 -------------------------------------------------------------------------------- 従来のプログラミング言語(FORTRAN,C等)では、デ−タと関数は全っく別物で あり厳然と区別されていた。このため従来のプログラミングは、所与の問題をデ−タと関 数に分けることであった。ただ単なる計算プログラムのように、デ−タが数値や文字以上 の意味を持たない場合、特にデ−タだ関数だという意識すらない場合もあるにはある。し かし何々システムというプログラム・レベルになると、果たしてデ−タと関数に区別する ことが適切であるのか疑問である。 ↓ そもそもデ−タというのは、ある現象の状態を表わすものであって、関数はその状態を変 化させるものと考えられる。つまりデ−タとその関数は表裏一体の関係にあるはずである。 ↓ 従来こうした枠組みを表現するコンピュ−タ言語がなかった。そのため無理に問題の方を 言語に合うように変形していたことになる。問題を変形、解釈しデ−タと関数に分解する 能力はプログラマにとって必須の技術的要件であった。これは永い間、疑いを挟む余地の 無いところであった。 ↓ 問題を自然に記述できる言語、Smalltalk やC++が開発された。デ−タと関数は一体の ものであることが明確に表現することが可能になった。その枠組みをオブジェクトと言う。 オブジェクトを用いてプログラムを作成することを、オブジェクト指向プログラミングと 呼ぶ。 ↓ -------------------------------------------------------------------------- |オブジェクトは、クラスを雛型として生成したインスタンスである。 | |クラスは、デ−タとそのデ−タをアクセスするための関数で定義される。 | |オブジェクトの持つデ−タは、基本的に外部からはアクセスできない。 | |オブジェクトの持つデ−タは、オブジェクトの関数でのみアクセスできる。 | | ↓ | |オブジェクトの内部は、ブラックボックス化されていると言ってよい。 | | ↓ | |オブジェクトにメッセ−ジを送って、デ−タを変更するというイメ−ジになる。| | ↓ | |(モジュ−ル性が高くなり、エラ−の少ないプログラミングが可能になる) | -------------------------------------------------------------------------- ↓ 結局オブジェクト指向プログラミングとは、オブジェクトを生成したり、消滅させたりす ることと、メッセ−ジにより個々のオブジェクトの内部状態(デ−タ)を変化させること。 これらのことによって稼働するプログラムを記述することであると言える。 1-2. C++の理解を妨げる要因 * 例題が悪い オブジェクト指向の理解の妨げになっているのは、適切にそれを説明している出版物が無 いことも一因していている。オブジェクト指向の説明に、海難救助用ブイをモデルにした ものが多いと、メッセ−ジ関係の図だけを載せ、その具体的なプログラムは載せていない とか。あるいは、普通の処理系にはないC++のタスク・ライブラリを使った飛行機の離 発着シュミレ−ションだとか。これはちゃんとプログラムが掲載されているが、自分で試 してみようがないので、結局よく分からない。またエディタ−を例にしたものもある。し かし文字列操作だけのエディタ−なんか、考えるのもめんどくさいし、例題にしては長過 ぎる。ともかく、色々例題はあることはあるのだが、どれも直感的ではないし、興味が湧 かないものばかりなのである。 * 説明が悪い 様々なところで書かれているOOP言語の理解の仕方は、先ずはオブジェクト指向と言う プログラミング・パラダイムである。C++のテクニックや文法を理解することよりも先 に、そのパラダイムを理解することが、何よりも重要であると言う。こうした話が買う本、 買う本に載っているので、とりあえずその線で努めてみるのだが、何も見えてこない。む しろ読めば読む程分からなくなって来るのが実情である。先程のメッセ−ジがいい例であ る。C++のどこにメッセ−ジがあるのだ。分からんのは自分が馬鹿だからか。もしそれ が分かったら素晴しいパラダイムが目の前に拡がるに違いない。そんな風にどんどん深み に入ってしまうのである。 これらの元凶は純粋なオブジェクト指向言語の Smalltalk で、 C++の説明をしていることにある。オブジェクト指向プログラムも出来るというC++ と純粋なSmalltalkとでは、機能が異なっているのだ。それに Smalltalk とC++の用語 が入り乱れ、ただでさえ分かりにくいのが、益々混乱に拍車を掛けるているのである。 * 習得期間のまやかし 従来の言語からOOP言語( Object-Oriented Programming ) を使えるようになるまでの 期間は、少なくとも半年から1年間は要すると言った議論をよく目にする。こんなことは どんな言語に関しても言えることであり、例えば BASIC や FORTRAN からC言語を使える ようになるまで、やはり半年ぐらいはかかるのである。それにC++を習得するには、従 来の言語をずっとやって来た人よりも、初心者の方が習得し易い。それはプログラミング のパラダイムが異なっているためであり、従来の人は頭の切り替えが難しいからだと言っ た議論もされている。何か色々デ−タを取って示したりしているが、確かにそれはそうか もしれない。しかし、エンジニアが本当に知りたいのは、そんな能書きよりも、OOPは こうやってプログラミングするんだというテクニックである。だいたいプログラミングす るだけのことに、パラダイム等と言う英語を持ち込んで来ること自体大げさ過ぎる。 * 生産性のまやかし 習得期間の話と同時に語られるのが、プログラミングの生産性である。C++を勉強し出 して、最初は生産性は低いが、半年ぐらい後から、ぐっと上がって来るともよく書かれて いる。それはそのようにプログラミングした場合の話であって、誰でもそうなるとは限ら ない。"他の言語よりも、生産性が向上する可能性が、場合によってはある"と言うべきで あろう。なにかC++を使えば必ず格段に生産性が上がるかの様な記述は、誤解を招く以 外にない。1つ言えることは、作成しようとするアプリケ−ションの基本となる、クラス ライブラリをきちっと作った後であれば、それはやや生産性は上がるだろうとは思われる。 それはC言語のライブラリに較べ、ライブラリのブラックボックス化の度合が、C++の 方が大きく出来るからであり、その分プログラマが細かい所まで、気遣う負担が少なくな るからである。 * シュミレ−ションに向いているなんて吹聴するな! まるでオブジェクト指向プログラミングそのものが、シュミレ−ションや平行動作の記述 に向いているかの様な表現は困る。シュミレ−ションする個々の要素を記述し易いとは言 えても、向いているまでと言うのは言い過ぎである。オブジェクト指向とシュミレ−ショ ンは別物である。C++ではたまたまタスク・ライブラリという見掛け上(あくまでも見 掛け上で、fork や exec 関数でプロセスを作るわけでない)、 平行動作を実現させるク ラスが用意されたので、シュミレ−ション的なプログラムも作れるよと言うことに過ぎな い。下手に向いているなんて宣伝するので、オブジェクトというのは全く独立したタスク、 マルチタスクのプロセスみたいなものと勘違いするのだ。小生は当初そう思いこんでいた。 C++ってのはすごいんだな−と感心していたのだ。 1-3. 参考文献等 -------------------------------------------------------------------------------- 以下に掲げた本や雑誌は、小生の目の前に並んでいるものであって、C++を理解しよう とすると、いかに本を一杯買わなければいけないか、示したかっただけである。決して読 者の皆さんに買って読んでくださいと列挙したわけではない。中には買って損する本も実 はあったりする。いや結構あるぞ。 -------------------------------------------------------------------------------- * "オブジェクト指向狂詩曲" は軽い読み物形式になっているが、なかなかである。 C++ にはメッセ−ジはない。ただクラスの関数をコ−ルしているだけなのだ。とズバリ書いて あった。この1行で、ずっと引掛かっていたメッセ−ジに対する謎が解消された。 * "Borland C++ ビデオテ−プ" はじっくり見れば、それなりに効果はあるのだろうが、 抽 象的な話が結構多く、決して初心者向きではない。Borland のマニュアルの方はなかなか 良い。EWSユ−ザも Borland C++ を1つ購入することを薦める。 NIHクラス・ライ ブラリを使うにも、 クラスの機能は Borland C++ ついて来るライブラリと良く似ている ので、参考にできる。 * C MAGAZINEは月間誌でありながら、内容が非常に優れている。 特に木戸研一氏 のオブジェクト指向の話は含蓄があった。一読を勧める。 * 全体的には雑誌等の記事は、あまり読まない方がいいとおもう。ある程度自分で小さなプ ログラムを組んでみて、ふんふんと分かった後に読んで見ると効果的かも知れない。 オブジェクト指向と Smalltalk : CQ出版社 C++入門 : CQ出版社 C++言語入門 : アスキ−出版局 オブジェクト指向プログラミング : アスキ−出版局 プログラミング言語C++ : トッパン オブジェクト指向狂詩曲 : 技術評論社 タオ・オブ・オブジェクト : 技術評論社 C&&C++入門 : オ−ム社(桐山清) Borland C++ 2.0マニュアル : ボ−ランドジャパン Borland C++ ビデオテ−プ : ボ−ランドジャパン Domain/C++ Programmer's Guide : Hewlet-Packard Company [Order No.017874-A01] Domain/C++ Version 2.1.0 Software : Hewlet-Packard Company Release Document THE ANNOTATED C++ REFERENCE MANUAL : Addison-Wesley Publishing Comapny Object-Oriented Design for C++ : PTR Prentice Hall,Englewood Cliffs, NJ 07632 TURBO C 初級プログラミング(下) : 技術評論社 "C++の勘どころ" : bit Vol.23,No.3(羽部正義) "OOP導入と効用と秘訣" : NIKKEI BYTE/JANUARY 1991 月間誌:C MAGAZINE : 日本ソフトバンク 月間誌:UNIX MAGAZINE : アスキ−出版局 ソフトウェア・エンジニアリングのための : YHP資料 オブジェクト指向入門 ObjectStore のカタログ等 : 東洋情報システム HP-UX用 C++/SoftBench のカタログ等 : YHP オブジェクト指向アプロ−チの実際 : YHPセミナ−・テキスト 1-4. C++とその関連用語 * オブジェクト指向とC++の対比 Smalltalk での表現 | C++での表現 Smalltalk は純粋なオブジェ -------------------------------|-------------------- クト指向言語で、オブジェク オブジェクト | クラス ト指向の説明がされる場合は、 インスタンス | メンバ変数 必ず引き合いに出されている。 メソッド | メンバ関数 オブジェクトにメッセ−ジを送る | メンバ関数の呼び出し * まぎらわしい用語の対比 演算子 - オペレ−タ 多重定義 - オ−バ−ロ−ド 多義化 - オ−バ−ロ−ディング 基底クラス - 基本クラス、ベ−スクラス 派生クラス - 導出クラス 継承 - インヘリタンス 多重継承 - マルチプル・インヘリタンス コンストラクタ - 構築子 デストラクタ - 消滅子 メンバ変数 - デ−タメンバ、クラス変数 仮想関数 - バ−チャル関数 仮想デストラクタ - バ−チャル・デストラクタ 抽象クラス - アブストラクト・クラス 純粋仮想関数 - 0で初期化した仮想関数 クラス階層 - クラス・ハイアラキ スコ−プ - 有効範囲 動的結合 - レイト・バインディング、後期結合、遅延バインディング 静的結合 - ア−リ−・バインディング、早期結合 親クラス - ス−パ−・クラス、汎用クラス 子クラス - サブ・クラス アドレス演算子 - & スコ−プ解決演算子 - :: * C言語に対する新しいキ−ワ−ド class : クラスの定義 this : クラスのインスタンス自身のポインタ private : メンバ変数、関数を外からアクセス出来なくする public : メンバ変数、関数を外からアクセス出来るようにする protected : メンバ変数、関数を派生クラスからアクセス出来るようにする friend : フレンド関数の定義 virtual : 仮想関数の定義、関連する用語に遅延バインディングがある new : インスタンスを動的に生成する delete : 生成したインスタンスを消滅させる cout : コンソ−ルに出力する cin : コンソ−ルから入力する const : 関数の引数の保護に使うと有効である register : この2つは実行速度を上げるのに効果があるとされるが、 inline : 慎重に用いる必要がある 1-5. コンパイル&リンクの方法 * CとC++プログラムの拡張子の取り決め << こういう様に決めてみては。 言語 | コマンド | ソ−ス | オブジェクト ------|----------|---------|-------------- C | $ cc | xxx.c | xxx.bin 注. Apollo ではC++のリンクに bind C++| $ CC | xxx.C | xxx.o コマンドは使えない。 * 通常のC++のプログラムの場合 cpc << コンパイル用コマンド。こういう専用コマンドを用意したらどうか。 ----------------------------------------- |CC ^1.C -A cpu,mathlib -c -b ^1.o -O -v cpp << 単独ファイルのコンパイル&リンク用コマンド。 ----------------------------------------- |CC -o ^1 ^1.C -O -v;^1 $ CC -o test test.bin test.o test1.o -O -v << リンクの例 * コンパイル・オプション [ C++コンパイラに対するオプション ] CC test.C -c : コンパイルするだけ。test.bin ができる。 CC test.C -F : C++ のソ−スコ−ドを C のコ−ドに変換して、表示する。 CC test.C -b test : コンパイルして実行モジュ−ルを test で作成する。 CC test.C -A a : ANSIに準拠してコンパイルする。デフォルト。c++cpp。 CC test.C -v : コンパイルの内容を詳しく表示する。 CC test.C -V : コンパイラのバ−ジョンを表示する。 CC test.C -I/usr/include/nihcl : #include ファイルを探すディレクトリを追加する。 [ Cコンパイラに対するオプション ] CC -g : デバッグ情報を出す。$ tb をやると出て来る。tb は Apollo 特有のトレ−ス情 報の表示コマンドである。 CC -O : -opt 3 と同じ。他のレベルでの最適化オプションは -W0,opt,n を使う。 [ 実行例 ] $ CC -V << C++のバ−ジョンを表示する。 @(#)Domain/C++ 2.1.0 $ CC r1.C -c -v << コンパイルの内容を表示する。 /usr/apollo/lib/c++cpp -D_ISP__M68K=1 -D_ISP__A8 ... C r1.C /usr/tmp/AAAa01234.i /usr/apollo/bin/cfront +L +a1 +fr1.C /usr/tmp/AABa01234.i /usr/apollo/lib/cc /usr/tmp/AABa01234.i -opt 0 -bss -nmsgs -usrch -b AABa01234 renaming AABa01234.bin to r1.bin removing /usr/tmp/AAAa01234.i removing /usr/tmp/AABa01234.i * C++インクル−ド・ファイル $ ld /usr/include/CC ( /usr/apollo/include/CC/bsd4.3 へのリンク ) Ostream.h arpa assert.h cc complex.h complex.hxx ctype.h dbm.h demangle.h errno.h fcntl.h fstab.h fstream.h generic.h generic.hxx grp.h iomanip.h iostream.h libc.h libc.hxx malloc.h math.h memory.h ndbm.h netdb.h new.h nlist.h osfcn.h osfcn.hxx ptrace.h pwd.h resolv.h setjmp.h sgtty.h stdarg.h stdarg.hxx stddef.h stdio.h stdiostream.h stdlib.h stream.h stream.hxx string.h strings.h strstream.h sys sysent.h syslog.h time.h ttyent.h vector.h vector.hxx vfont.h 1-6. NIHクラス・ライブラリについて * 使用に当たっての注意 NIHとは National Institute of Health の略で、フリ−ソフトウェア扱いになってい る。唯一の参考書は『Data Abstraction and Object-Oriented Programming in C++』 だ けである。( ISBN 0471 92346 X )。NIHクラス・ライブラリを省略して NIHCL とも呼 ばれている。内容的には、Smalltalk のクラス階層に似せて作られたクラス・ライブラリ であり、 市販のOODB( Object Oriented Data Base )ソフトにも組込まれた実績もあ る。使用にあたってはヘッダ−・ファイルとサンプル・プログラムから使用方法を探るし かない。 以下は Apollo の X-Window のテ−プに最初から入っていたものである。おおむねコンパ イル&リンクはできたが、タスク・ライブラリの Semaphore、Scheduler は Apollo では エラ−がでて途中で止まってしまった。全体的な感想は使いこなすのは相当大変であると いう感じである。 * コンパイル&リンクの基本方法 コンパイル用コマンド ------------------------------------------------------------------------------- |CC ^1.C -c -b ^1.o -O -A cpu,mathlib -I/usr/local/include -I/usr/include/nihcl 単独ファイルのコンパイル&リンク用コマンド ------------------------------------------------------------------------------- |CC -o ^1 ^1.c -O -A cpu,mathlib -I/usr/local/include -I/usr/include/nihcl 続く | /usr/local/lib/libnihcl.a /usr/local/lib/libnihclvec.a -v 単独ファイルのリンク ------------------------------------------------------------------------------- |CC -o ^1 ^1.o -O -A cpu,mathlib /usr/local/lib/libnihcl.a 注.最後の -v はコンパイルなどの状況を画面に出すオプションである。 [ vector クラスを使わない場合は、NIH基本クラスだけでよい ] $ CC -o ^1 ^1.C -O -A cpu,mathlib -I/usr/local/include -I/usr/include/nihcl /usr/local/lib/libnihcl.a -v [ Makefile を使う場合 ] $ /bin/make test または /bin/make だけでもよい Makefile ---------------------------------------------------- |SHELL = /bin/sh |CC = CC |SYS = BSD | |NIHCLINCDIR = /usr/include/nihcl |NIHCLLIBDIR = /usr/local/lib |CCFLAGS = -I/usr/local/include |NIHCLLIB = ${NIHCLLIBDIR}/libnihcl.a |CFLAGS = -I${NIHCLINCDIR} ${CCFLAGS} | |all: test |test : $$@.o | ${CC} $@.o -o $@ ${NIHCLLIB} |# /../../test コメントを外すと実行する |test.o : | ${CC} -c $*.c $(CFLAGS) * NIHクラス・ライブラリのインスト−ルと構成 $ ld /domain_examples/CC_examples TMLib.tar.Z apollo-examples att-examples codelibs-examples iv.tar.Z nihcl.tar.Z $ wd /domain_examples/CC_examples $ /bin/start_csh % uncompress < nihcl.tar.Z | tar xf - /usr/local/lib/libnihcl.a << クラス基本部の使用には、この2つの部分でよい。 /include/errlib.h,errors.h /lib/libnihclvec.a << ベクタ−型クラスのライブラリ。 /lib/libnihclmi.a << 多重継承版クラス基本部。 /lib/errgen_tab /bin/errgen //node_xxx/domain_examples/CC_examples/nihcl-3.0 README リリ−ス・ノ−ト INSTALL インスト−ルの説明 APOLLO-README アポロ・ユ−ザのためのインスト−ルの注意 [lib] NIHクラス・ライブラリの基本部 [test] NIHクラスのサンプル・プログラム [vector] ベクタ−型クラスのソ−ス・プログラム [vectest] ベクタ−型クラスのサンプル・プログラム [errfac] エラ−処理のソ−ス・プログラム [ex] 練習問題のサンプル・プログラム。BigInt クラスなどがある。 * NIHクラスのサンプル・プログラムを試す ( nihcl-3.0/test ) % date << date.c だけコンパイル&リンクする CC -I../lib -g -I/usr/local/include -DNE_ .. date.c -o date ../lib/libnihcl.a -g 関連ファイル: date date.c date.in(入力例) date.v(出力例) * 練習問題のサンプル・プログラムを試す ( nihcl-3.0/ex ) % make ex5-8 << 'up_date' と表示されたら % rm ex5-8 とやるとよい。 Makefile ex5-8 部 ------------------------------------- |ex5-8.o: ex5-8.c | $(CC) $(CFLAGS) -I${NIHCLVECINCDIR} -c $*.c |ex5-8: $$@.o ${NIHCLLIB} ${NIHCLVECLIB} | $(CC) $@.o -o $@ ${NIHCLVECLIB} ${NIHCLLIB} ${LFLAGS} * NIHクラスのヘッダ−ファイル $ ld /usr/local/include errlib.h errors.h $ ld /usr/include/nihcl ( /bsd4.3/usr/include/nihcl へのリンク ) ArrayOb.h Arraychar.h Assoc.h AssocInt.h Bag.h BitBoard.h BitVec.h Bitset.h ByteVec.h Collection.h Date.h Dictionary.h DoubleVec.h ExceptAct.h Exception.h FDSet.h Float.h FloatVec.h Fraction.h Heap.h HeapProc.h IdentDict.h IdentSet.h IntVec.h Integer.h Iterator.h KeySortCltn.h Link.h LinkOb.h LinkedList.h LongVec.h LookupKey.h OIO.h OIOTbl.h OIOfd.h OIOnih.h OIOstream.h Object.h OrderedCltn.h Point.h Process.h Random.h Range.h Rectangle.h Regex.h Scheduler.h Semaphore.h SeqCltn.h Set.h SharedQueue.h ShortVec.h SortedCltn.h Stack.h StackProc.h String.h Time.h Vector.h bitstreams.h nihclIO.h nihclconfig.h nihclerrs.h nihclerrsx.h regex.h の63個 /usr/include/nihcl にあるヘッダ−ファイルの以下の9個は、/nihcl-3.0/vector のも のと同じであり、残り54個は /nihcl-3.0/lib のものと同じである。 BitVec.h ByteVec.h DoubleVec.h FloatVec.h IntVec.h LongVec.h ShortVec.h Vector.h bitstreams.h ヘッダ−ファイル以外: Template_c, Template_h * NIHクラスの階層 NIH---Object--Collection--SetCltn-----OrderedCltn--SortedCltn--KeySortCltn |-Random |-ArrayOb |-Stack |-FDSet |-Arraychar |-LinkedList |-Interator | |-Heap |-Class |-Bag---------Dictionary--IdentDic | |-Set |-IdentSet |-Vector------DoubleVec |-Rectangle |-FloatVec |-Point |-LongVec |-Bitset |-IntVec |-Integer |-ShortVec |-Float |-ByteVec |-Fraction |-BitVec |-Time |-Date |-Nil |-LookupKey---Assoc | |-AssocInt |-String------Regex |-Link--------Process---StackProc | |-LinkOb |-HeapProc |-ShardQuence |-Semaphore |-Scheduler < コレクション・クラス > : 集合を扱うクラス Collection, SetCltn, OrderedCltn, SortedCltn, KeySortCltn Stack, LinkedList, Heap, ArrayOb, Arraychar Bag, Dictionary, IdentDic, IdentSet, Set コレクションを走査するクラス - Iterator(反復子) コレクションを探索に使うクラス - LookupKey < コル−チン・クラス > : Process, Scheduler, Semaphore < 拡張デ−タ型・クラス > : Integer, Float, String, Date, Time など