C プログラマのための C + + 入門 実践 0 + + ゼミナー よレ なオプジェクトとファイル内スコープの List 2 のコンパイル結果 static なオプジェクトのコンストラクタ / * リードオンリーメモリエリアに配置指示 を section . rodata / * 文字列ラベル 0 . LCO: デストラクタは前回とほとんど同じなので / * "Hi,I am MycIass%n" 文字列リテラル . byte 0X48 , 0X69 , 0x2c , 0X49 , 0X20 , 0X61 , 0x6d , 0X2 の Ox4d , 0X79 . byte 0X63 , 0x6c , 0X61 , 0X73 , 0X73 , 0x も 0X0 割愛しました。 / お文字列ラベル 1 CI : / * 宅 s started%nn 文字列リテラル . byte 0X25 , 0X73 , 0X2 の 0X73 , 0X74 , 0X61 , 0X72 , 0X74 , 0X65 , 0X64 static なオプジェクトについては , 全処 . byte 0xa,0x0 / * 文字列ラベル 2 . も C2 : / * "8s ended%n" 文字列リテラル . by こ 0 0X25 , 0X7 ] , 0X20 , 0X65 , 0x6e , 0X64 , 0X55 を 0X64 , 0xa , 0X0 理で 1 回だけ構築されるという性質を実現 / 物ラベル ' 引 oba ドをグローバルにする . Ob ー引 Ob 引 / * 読み書き可能なデータメモリエリアに配置指示 .data するために , コンパイラはわざわざワーク / * 高速に読み書き可能なようにアドレスを整合 ・ p2a lign 2 / * tkbug 情報 ・ t ン e GlObaI.@object 用の変数まで用意してそれをチェックする / * サイズ 4 バイト。 char * mes の実体サイズ . size Global,4 / * ラベル ' 引 oba ドに現在のアドレスを記録 / * 0 で初期化された 4 バイトのエリアを指示 、 zero 4 コードを出力しています。 C + + では C に比 ラベル 'BlockStatic. 15, をローカルに指示 .local BlockStatic. 15 / * 0 初期化工リアに 4 バイト確保 . comm 田 ockS ねし ic は 5 , も 4 べるとシステム側の負担がかなり増加して / * 高速に読み書き可能なようにアドレスを整合 ・ p2align 2 / * 引 ockSt 北 ic を 2 回初期化しないためのフラグを生成 . e —$tmp—O.16.@object いるのがここからも読み取ることができま / * フラグの実体を 4 バイトと指定 ・ size ー $tmp ー 0.16 , 4 / 第フラグのためのラベル -$tmp—O. 16: な 0 で初期化された 4 バイトのエリアを指示 . zero 4 すね。 .section . rodata なリードオンリーメモリエリアに配置指示 / * 文字列ラベル 3 .LC3: この MyCIass の実体は 1 つのレジスタで / * 第も oca ー Statig"- 文字列リテラル . byte 0X42 , 0X60 , 0X6 新 0X63 ′ Ox6b , ℃ X20 , 0X53 , 0X74 , 0X61 , 0X74 . byte 0X69 を 0X6 0X0 / * プログラムコードメモリエリアに配置指示 割り当てることができるのですが , GCC . text / * 高速に実行可能なようにアドレスを整合 . p2a lign 2 , 0X90 / * Debug 情報 —tcf—O .@function はそのようにはしません。 C + + のクラスオ / * 引 ockS いし ic のためのディストラクタ実体 ー tcf ー 0 : / * スタックフレームを作成 pushl %ebp プジェクトの扱いをバグを発生させないで / * # # exit() が呼ばれたりすると突然変数の寿命が終わる movl %esp,%ebp / * # # そのためにコンパイラは工夫したコードを生成 subl $8,tesp / * if (mes) の実体 cmpl $O , 引 OCkSta に土 0.15 最適化の対象にするのはかなり困難なため / * mes = = 0 なら . L25 へジャンプ je . も 25 / * 意味が不明なスタック調整 歳 d 引 $-4,8esp に , 部分的に見るとこのような単純なクラ / * mes をスタックへ push ー B IockStatic. 15 ーー / * "%s ended%n" へのポインタをスタックへ pushl $. LC2 スでも出力されるコード自体は逆にソース push ーー SF 十 88 / * stdout のラベル。ライブラリ内に実体がある / * fp て i 北 f ( ) の呼び出し call fprintf / * if の終わり 25 : に素直に反映する部分もあります。 / * スタックフレームの廃棄 leave / * 呼び出し元へ復帰 て e し / * リードオンリーメモリエリアに配置指示 . sec セ土 on . て Od クラスに割り当てられる / * 文字列ラベル 4 .84 : / * Au に 0 文字列リテラル . byte 0X41 0X75 , 0 74 , 0x6f , 0X0 メモリ領域 なプログラムコードメモリエリアに配置指示 . text / * 高速に実行可能なようにアドレスを整合 ・ p2align 2 , 0X90 / * 加をグローバルに。ここを初期化ライプラリが呼ぶ * ノ .globlmain / * Debug 情報 ・ type main を@function 今まで連載で登場したクラスのコンスト main : ラベル main ラクタはすべてクラス自体の定義の中で定 義されていたので , コンストラクタはその 定義された位置に直接コンパイラがコード を埋め込むインライン関数の例だけでし た。実際のクラスではそのようなことは少 なく , コンストラクタ自体が実体を持った 関数であることがほとんどです。 このようなコンストラクタの場合には , メンバ関数 ( コンストラクタもメンバ関数 のひとつ ) を持つ C + + のもうひとつの特徴 が見えてきます。それは , C ではコンパイ ラが行うことがまったくない動的なメモリ 管理です。 C では malloc ( ) や free ( ) を駆使 してプログラマがメモリ管理を行わなくて はなりませんが , C + + では独特な機能が組 み込まれています。次回はこの機能につい て説明します。 / * 引 ockSt ic を 2 回構築しないようにフラグを検査 / * すでに構築済みならジャンプ な mes = ini の処理。たった 1 命令 / * 意味が不明なスタック調整 / * oc 引 S に a に土へのポインタ / * "8s sta てに ed 第”へのポインタ / * stdou セへのポインタ / * fprintf を呼ぶ / * スタック補正 な初期化済みフラグをセットする / * 意味が不明なスタック調整 / * ディストラクタへのポインタ ノ * 訛 exi 日 ) を呼び出す ( プログラムはこれは指示していない ) / * スタック補正 / * 初期数身の場合の入り口 / * AutO の mes = inito これも 1 命令 / * Au し 0 物へのポインタ ノ * ” s started%n" へのポインタ / * stdo へのポインタ ノ * fp て土 n に f を呼ふ / * スタック補正 / * if (mes) の処理。み uto のもの。 / * mes = 0 でジャンプ な意味が不明なスタック調整 / * mes の実体をスタックへ / * "%s ended \ n ”へのポインタをスタックへ / * stdout へのポインタ / * fprintf を呼ぶ / * mes = = 0 のときここにくる / * return 0 を生成 ノ * ebx を復帰 / * スタックを開放 / * 終了以 cmpl $0,—$tmp—O.16 jne . L17 movl $. LC3 , 引 ockS し北 ic. 15 addl $-4 ,%esp pushl $. LC3 pushl $. も CI pushl $—SF 十 88 call fprintf addl $16,8esp movl $1,—$tmp—O.16 addl$-12,%esp push ー $ ーーセ cf ー 0 ca 日 atexit addl S16 ßesp 、も 17 : movl $. LC4,-4(%ebp) addl $-4 ,%esp pushl $. LC4 pushl $. LCI push ー $——sF 十 88 call fprintf addl $16,%esp cmpl $0,-4(tebp) je . L32 addl $ -4 洋 e 叩 pushl -4(%ebp) pushl $.LC2 pughl $—sF 十 88 ca fprintf 32 : xo て一 %eax,%eax movl -40(%ebp) *ebx leave 64 C MAGAZINE 2001 6
再考する気になった。 その結果 , 単リンクリストのより根本的 な問題に首を突っ込むことになった。話を 単純にするため , これを問題「以前」の問題 に要約する。この問題は次の 3 つの側面が ある。 ・ STL コンテナに新しい要素を追加する 汎用のメンバ関数は、 insert(where, v a ⅳ e ) のような形をしている。ここで wh e 「 e は反復子であり , それが指す要素 の直前に新しい要素を挿入する。しか し単リンクリストの場合ーリンクを 更新する必要がある要素は , where が 指す要素の向こう側にある ・テンプレートクラスⅱ st 固有のメンバ関 数により , リストオブジェクトから部 分リストをつなぎ合わせることができ る。つなぎ合わせる部分リストを , 同 じリストオブジェクトから取ることさ えもできる。しかし , こでもまた , sp lice(where, 0 物 e 「 list) のような呼び出 しは、部分リストをつなぎ合わせる場 所の直前の要素を指す反復子 where を とる ・ STL コンテナの要素を削除する汎用の メンバ関数は , erase(where) のような 形をしている。ここで whe 「 e は削除す る要素を指す。しかし , こでもまた , 要素を削除するためには , 反復子が指 す要素の 1 つ前の要素のリンクを更新 しなければならない 単リンクリストの中で反復子をさかのば らせるにはたった 1 つの方法しかない。列 の先頭から始めて要素を順に手繰り , 次の 要素が目標のものであるような要素のとこ ろで止まる。この操作は明らかに線形時間 を要する。つまり , この処理を実行する時 間は , リストが管理する要素の数に比例し て増えてしまう。 L は反復子の操作は定 数時間であることに依存して注意深く設計 されている。であるから , これは大きなオ ーバヘッドになる。線形時間を要する反復 子の計算が必要な操作の場合 , 挿入 , つな ぎ合わせ , 削除を定数時間で行うことはで きない。 この問題に対する解の 1 つは , このとん でもない時間複雑性を単に受け入れてしま うことだ。 insert_after , splice_after, erase er という感じの名前の非標準のメンバ 関数を追加することができる。これらはそ れぞれ , 列で通常の場所の前の要素を指す 反復子を引数としてとる。単リンクリスト を操作する際にまさに注目する場所である。 しかし , このやり方は無作法だとわかっ た。万能な訂 L 記法は , それなりの深い理 由で選ばれていた。 begin() ( これは列の最 初の要素を指す ) と end ( ) ( これは列の最後 の要素の次の場所を指す ) の間の任意の反 復子の値に対し , その前の位置の話をする ことに意味がある。空の列に対し , begin() は end ( ) に等しく , この場合でもそのような 反復子のすべてが意味を持つ。 しかし , これは上の 3 つの・。血 er " 関数の 場合には正しくない。こでは , 列の先頭 を指す方法がない。さらに悪いことに , 列 の末尾を超えた場所のすぐ後ろに何かを挿 入するというのは意味をなさない。これら の問題の両方に手当てをすることはでき る。しかし , その結果は依然としてつぎは ぎのままだ。さらに , それらすべてを別に しても , 既存の L コンテナの仲間とまっ たく異なる。 それで私は別のやり方を選んだ。典型的 なリスト ( または赤黒木 ) 反復子は , それが 指すノードへのポインタを持つ。しかし , 私はこのポインタを別のもので置き換えた。 つまり , 反復子が指すノードへのポインタ へのポインタである。リストコンテナは , リスト最初のノードを指すポインタ _First を格納する。リストが空であれば , _First には空ポインタを格納する。さらに , 各ノ ードは , リスト内の次のノードを指すポイ ンタ _Next を格納している。ノードがリス トの末尾にある場合 , Next には空ポイン タを格納する。最後に , 反復子は , ポイン タへのポインター Ppn 。 de を格納する。この Standard 記法では , ・ begin ( ) は & ー Fi 「 st を格納する反復子を 返す ・ + 舸 te 「は , _Ppnode に格納された値を & Next ( * ー Ppt 「 ) で置き換えることで , 反復子 iter をインクリメントする List 1 に入れ子クラス const_iterator の 定義を示すこれは , 単リンクリストのテ ンプレートコンテナ slist に対する定数反復 子である。すべての、 L コンテナが求める 多数の型定義も , List1 であわせて示す。 れは , ばかみたいに単純であれという約束 は満たしている。それでもなお , この反復 子はいつでも , リストに普通に生じる変化 のすべてに対応して更新する必要があるリ ンクのアドレスを持ち運んでいる。結果と して , 単リンクリストのこの実装は , 定数 時間で挿入 , 削除 , つなぎ合わせを行うと いう約束を満たしている。 ー下を向いて歩こう A Walk on the Down Side ものごとの常だが , ここには引っかけが ある。このやり方の問題点は , 反復子が , 実際に自分が指しているリストノードの 1 のぞ つ前のノードの内部を覗き見しているとこ ろにある。すべてが静止したままである限 りこれはうまくいく。しかし , 次のことを 考えてみよう。 ・反復子 where が指す要素の 1 つ前に要 素を 1 つ挿入する場合 , where は , 新 しく挿入された要素を指してしまう ( よ く考えてほしい ) ・ where が指す要素の 1 つ前の要素を削除 すると , where は無効な反復子になっ てしまう この挙動には驚かされるし , 望ましいも のとはいえないと指摘されるかもしれない。 map, set, 双方向リストを指す反復子の長 所の 1 つに , それが指す要素が存在し続け る限り有効であることがある。リストの場 合 , それをつなぎ合わせることさえでき , 反復子はそれでも有効である。そのような Standard C ℃ + + 7 /
Fig. 1 プリミティプ型と参照型 intx = 3 : Data y = new Data(3); 3 代入と変更 Fig. 2 List 5 の実行結果 ( 注 1 ) int など , 最初から定義されている型 参照 ( ポインタ ) での使用 の va の場合直接の使用 参照 ( ポインタ ) での使用 ℃言語の場合直接の使用 TabIe 2 プリミティプ型と参照型の相違 :Data value = 3 基本型 ( 注 1 ) 〇 プリミティプ型 〇 〇 集成体型 ( 注 2 ) 〇 〇 参照型 〇 List 6 2 : 4 : 6 : 8 : 9 : 10 : 11 : 12 : 13 : ) 14 : 16 : 17 : 18 : 19 : ) 20 : 22 : 24 : 25 : 26 : 28 : 29 : 30 : 31 : 32 : 33 : } スタートアップ Ja a Java 言語事始 インタフェイス型の例 ( Speak. java ) * Speak. java 5 : interface SpeakabIe{ public void speak( class Enshou implements SpeakabIe{ pub lic void speak ( ) { system. 0uしPてin凵れ(”百年目と思いました” 15 : class Kosan implements SpeakabIe{ public void speak( ) { system ・ ou し prin 凵れに今なんどきだい ? つ・ 21 : class Speak{ public static void main(String[ ] args) { SpeakabIe 町 S = new Enshou( s ・ speak( s = new Kosan( s. speak( ( 注 2 ) 配列型や構造体型など ーインタフェイス型 プリミテイプ型と参照型の相違はしつか り理解してください。とくに C から移って きた人は注意すべきところです。 C 言語と の比較を TabIe 2 にあげておきます。この 特徴は , 人によっては制限と見るかもしれ ません。しかしこれによって Java の言語と しての堅牢性が保たれているのです ( もっ とも SmaIItaIk 派からは「プリミテイプ型を 特別扱いするなんて汚い仕様だ」と言われ そうですが ) 。 ークラス型 これは前回も説明しました。ある「クラス」 を元にして作られる「オプジェクト」を保 持するための型です。 例 : Data d = new Data( クラスのインタフェイス・・・・・・つまり「ど ういうメソッドがあるか」だけを決めてお いて , そのメソッドを持っているクラスを 保持できるようにした型です。 これだけではわかりにくいので例をあげ ましよう。 List 6 を見てください。 5 ~ 7 行目 で class の代わりに inte ace が付いて宣言さ れているのがインタフェイスと呼ばれるも のです。 あ , それから今までは 1 つのファイルに 1 つのクラスだけを記述していましたが List 6 のように複数のクラス宣言やインタ フェイス宣言を記述することもできます。 ただしこれはあまりいいやり方ではありま せん。別ファイルにすると見にくくなりそ 。読者のみなさ うだからこうしたので・・ んが書くときは 1 つのファイルに 1 つのク ラスとしてください。 話を戻します。インタフェイス SpeakabI e では speak() というメソッドが宣言されて います。こうすると , speak() というメソ ッドを持っているクラスを Speakable とし て扱うことができるのです。クラス Ensh ou , クラス Kosan は , クラスとしては別で すが , どちらもインタフェイス Speakable を implements しているので , Speakable 型 として取り扱えるわけです。 インタフェイスについては , 回を改めて ー修飾子とデフォルト値 後にまとめて述べます。 配列型も参照型の一種です。これは少し ー配列型 詳しく解説します。 クトのフィールドには代入できるかもしれ ことはできませんが , それが指すオプジェ nal と宣言された参照型の変数に代人する ただⅱ nal の意味には注意してください。ⅱ 意味はプリミテイプ型のときと同じです。 ansient, volatile) を付けることができます。 ublic , protected , private , static , final , 仕 参照型にも , 先に述べたような修飾子 ( p ません。 スタートアップ Java 69
プログラミング技術情報誌・ C マガジン 0 C 0 N T E N T S 。 = 。使いやすい ユーザインタフェイスを求めて 12 アプリケーションと Web ページのデザインフィンローダ ユーザインタフェイスの定義 人間というシステム ユーザインタフェイスの基本 ユーザインタフェイスを意識したデザインの例 。 = , Mac OS X アプリケーション開発力イド PARTI Mac OS X の概要 PART2 開発環境の準備 PART3 アプリケーションの開発 (Carbon 編 /Cocoa 編 /Java 編 ) GetInt0 C WorId ! ! ー C 言語入門講座 く第 3 回 > 演算子と制御文 Pa 2 小薗光典 / 中井信会 c プログラマのための c + + 入門実践 C + + ゼミナール く第 3 回 > コンストラクタとデストラクタ吉野智興 スタートアップ J ava —Java 言語事始く第 3 回 > データ型と演算子毛呂宗夫 Q&A プログラミング相談室く書式文字列と 16 進数 > 毛呂宗夫 Standard C/C + + 『単リンクリスト』 p. J. 円 auge 「 / 熊谷典大訳 8 なて叮 77 のオブジェクト工房く第 3 回 > 文字コードの変換処理 EnjOY PerI Programming モジュールを活用しようく第 5 回 > HTML の解析結城浩 Ruby マスターへの道 く第 2 回 > 拡張ライプラリの作成 ( 2 ) 前田修吾 アルゴリズム入門プログラミングの宝箱 く第 2 回 > 探索春日伸弥 / 紀平拓男 画像処理を極めるアルゴリズムラボ く第 21 回 > デジタル画像での図形描画⑦スプライン曲線 , ベジェ曲線など 昌達 K'z 32 真紀俊男 6 1 -3 4 -3 0 6 3 8 -3 -3 6 6 7 7 8 8 9 9 0
ネットワークプロクラミンクのアトリエ の URL に表示を戻す「 Back 」は , Brow::Can GoBack() で Back 可能かどうかについて問 い合わせ , MBrow::Back() で実際の Back 処 理を行います。これらはすべて nsIWebNavi gation インタフェイスに処理を依頼します。 実装例については付録 CD - ROM に収録さ れている Navigation. cpp をご覧ください。 クロムクラス (MChrome) このクラスは , いくつかの定められた XPCOM インタフェイスを実装することに より , それを介して nsWebBrowser からの コールバックを受け , これを MBrow クラス に通知します。 実際に装備しているインタフェイスは , 次のものです。 ・ nsIWebBrowserChrome プラウザクロームとしての基本的インタ フェイスです。 ・ nsIWebProgressListener ページローディングの進行状況の通知を 受けるためのインタフェイスです。 ・ ns 旧 aseWindow 一般ウインドウとしての操作をつかさど るインタフェイスです。 ・ nsIPrompt 各種プロンプトダイアログを表示するた めのインタフェイスです。 ・ nslURlContentListener U 糺オープン開始時に , 当該インタフェ イス内の OnStartURIOpen() メソッドがコー ルされます。このメソッドにより , スキー ムやターゲット名 , URL の内容に応じて , 処理をインターセプトすることが可能にな ります。 ・ nslInterfaceRequestor オプジェクトがインプリメントしている Li st 1 MCh 「 ome クラスのコンストラクタ MChrome: :MChrome( ) . mBrowserWindow(nsnull ) , mBrowserShell (nsnull ) NS—INIT—REFCNT( mgBrowserList.push—back(this); List 1 MCh 「 ome クラスのインタフェイス取得 NS—IMETHODIMP MChrome: :GetInterface(const nsIID &aIID, void** alnstanceptr) retu て n QueryInterface ( al ID , alnstanceptr); インタフェイスを取得する方法を定義する インタフェイスです。この nsIInterfaceRequ estor は , 一般の XPCOM とは少し異なった 形でインタフェイスを装備するためのイン タフェイスです。一般の XPCOM では , lnte rface-A から Interface-B が QueryInterface ( ) でインタフェイスを得られる場合 , その逆 の Interface-B から Interface-A も取得できま すが , nsIInterfaceRequestor は , 一方向の 取得のみを可能にします。この場合は , Qu erylnterface ( ) ではなく , GetInterface ( ) で 取得します。 前述の nsIDocSheII は , nsWebBrowser に より , nsIInterfaceRequestor 経由で保持さ れています。よって , nsIWebBrowser より , QueryInterface ( ) ではなく , GetInterface ( ) により , nsIDocSheII を取得します。 クロームクラス定義 MChrome クラス (List 13 ) では , 装備す るインタフェイスを継承し ( List13- ( a ) ) , そ れらのメソッドの定義をします。この定義 は , NS_DECL_ISUPPORTS , NS DECL NSIWEBBROWSERCHROME などのマク 口により , 展開されます (List 13- (c)) 。 メンバ変数として , プラウザとの関連付 けを保持するために MWind, MBrow へ のポインタを持ちます ( List13- ( d ) ) 。また , プラウザリスト ( 生成した全クロームイン スタンスを保持する MChrome* 型の STL vector 配列 ) を static 変数として持ちます (List 13- ( e ) ) 。 MBrow クラスとは , friend クラスとなり , MBrow クラスのメンバへのアクセスを容易 にしています ( List13- ( b ) ) 。さらにマクロに より , AddRef() , ReIease ( ) , QueryInterfa ce ( ) を実装しています ( List13- ( g ) ) 。 生成 / 破棄 MChrome クラスのコンストラクタでは , プラウザリストに自分自身を追加します (L ist 14 ) 。 アクセッサ List 15 は , このクロームインスタンスに 関連付けられた MWmd, MBrow へのアク セッサメソッドです。ポインタへの参照を 使用して , 右辺値参照 , 左辺値代入の両方 ができます。 インタフェイス MChrome::GetInterface ( ) は , 外部より の GetInterface ( ) を処理します (List 16 ) 。 ns IInterfaceRequestor インタフェイスとして 呼び出されます。 こでは , すべて QueryInterface() へ処 理を与えることにしているため , 特別な処 理は行っていません。 ステータス MChrome::SetStatus ( ) は , HTML ドキュ メントからのステータス文字列の通知を行 います ( List 17 ) 。 nsIWebBrowserChrome インタフェイスとして呼び出されます。 STATUS_SCRIIYr は Javascript からのも の , STATUS_LINK は HTML ドキュメント List 1 BrowserWindow と BrowserShelI のアクセッサ MWind*& MChrome: :Browserwindow( ) return mBrowserWindow ー て ow * & MChrome: :BrowserShell ( ) return mBrowserShel 嵭 技術を知って実践しよう ! ネットワークプログラミングのアトリエ 1 2 /
特集 2 Mac 05X アフリケーション開発ガイド れたプロジェクトには main. m というソース C 特有のものですが , #include と同様 , ファ ジェクトの run メソッドを起動する関数で と MainMenu. nib などがあらかじめ登録され イルの取り込みを指示するものです。ただ す。詳細は Developer Help Center の「 NSAp し , 2 回以上 , 内容を取り込まないように p ⅱ ca ⅱ on 」を参照してください。 ています (Fig. 8 ) 。 main. m の中身は List 5 の します (#pragma once のあるインクルード とおりです。 1 行目の「 #import 」は Objective- もちろん , この中身のない main. m だけで ファイルをインクルードしたのと同じ結果 は真っ白なウインドウが 1 枚開かれるだけ ー a 旧 . m になる ) 。 でプログラムとしては何の役にも立ちませ NSApplicationMain というのは , 内部で ん。そこで , 次のステップに進むために アプリケーションオプジェクトの発生と , 「 Groups & Files 」の一覧に表示されている メインの nib ファイル [ 注 13 ] をロードし , アプ [ 注 13]Interface BuiIder によって生成され リケーションオプジェクトを nib ファイルの るファイル。 nib は NeXT lnterface Builder の頭文字をとったものという説が有力 所有者としてから , アプリケーションオプ Fig. 12 MyCont 「 0 Ⅱ e 「クラスの作成 ( a ) NSObject クラスを継承する MyCont 「 0 Ⅱ e 「クラスを作成する ・ 0 0 M M 。叫曲 as e & ・ lmages Sounds List #import く C000a / C000a. h > 土 n main(int gc , 00n8 セ char *argv[ ] ) return NSAppIicationMain(argc, argv); Fig. 10 独自ビュークラスの作成 ( a ) Classes タブに切り替えて NSView を選択する 0 0 0 MainMenu.nib a55 & images Sounds lnstances lnstances 田十十 v 工信 ng. 0 切 e ( t NSOb 第は Fi 「 5 【 R ponde 「 旧ⅲ 5P2 ( tO 「 旧 Pa には 0 NSM にれ 0 NSMenuItem NSResponder NSAppIication NSDrawer NSBox NSCI ゆⅥ ew ・ NSCon な NSBrowser マ マ 71 ・ 1 ・ 2 ・ マ SV NSArray NSM リい b に A 「 y NSCe 日 (b)Add Outlet と Add Action を選択して Outlet と Action を追加する Fo 「 m 誂し Subclass lnstantiate Edit ロ a 弱 Add Action ↓ 0 0 0 M M 今叫 ⅲ 5 ね n ( es ( iasse 、 jmages Sounds 0 、田、△ N50 切 t 0 ー 71 ・ F ⅳ st 5 po れ d 旧 5 は 1 ・ 2 ・ マ My ( 0 飛「 OII 0 破厄 t & myView A れ 5 t25t1. t05 に : NSA My ( 0 「 0 リ マ マ マ ↓ ↓ ( b ) メニューから SubcIass を選んで子クラスを作る 「 0 「 m ( は sses Classes Subclass lnstantiate Add OutIet ↓ ( c ) 作成した子クラスの名前を M iew にする 0 0 0 MainMenu.nib 5 ね n ( es ( & se 、 lmages Sounds 田十十 NSMenu NSMenultem NSResponder NSAppIication N SDrawer NSView NSBox NSCIipView NS 〔 on 引 マ マ マ MYView マ マ 47 MacOSX アプリケーション開発ガイド 特集 2
List g-st 「 dup—printf() の使用例 #include く glib. h> #include く sys/types. h> #include <sys/stat. h> #include く fcntl . h> #include く signal.h> #include く e てて no. h> static void sigh(int signum) 9 ー p て土北 ( "%s*nn, g—strsignal ( signum ) static void error—signal (void) int fd; signal ( 2 , sigh fd = open("non-exist—file", O—RDONLY); gchar* s セて一 str = g—strdup—printf( ” E てて 0 て : %s%nn,g—strerror(errno) sIeep(3); g ーヒ土 me て一 S セ a てセ ( gt gt g—timer—new( リ GTimer* gt; static void し土 me て ( void ) #include く g は b. h 〉 ストップウォッチの例 List 引 eep ( 1000 g-free ( s セて g ー p て土れ t ( ”宅 s n % st て LiIlllX l) 間町Ⅲ lllll 川 TIPS List パスの分解 #include く glib. h> static void sp lit—path ( gchar* path ) gchar* dirname; gchar* basename; dirname = g—dirname ( path basename g—basename(path); g ー P て土北 ( s ( ゆ ) つ宅 s ( ゆ ) 宅 s ( ゆ ) 貊” path, path' di て name, dirname' basename' basename g—free( dirname Fig. 3 basename と dirname 関数名 basename ( g-dirname() はメモリを確保して結果を格納する g—basename() g—print("%f%nn, g—timer—elapsed(gt,NULL) g—timer—destroy(gt); 手間なので , こうやって最初からあると便 利に感じます。 ちなみにこの関数は , Win32 環境で GLib を使用した場合も正しく動作するはずです。 前述したように , g_dirname() のみメモリ を確保するのでメモリの解放を忘れないよ うにしなければなりません。なぜ g_dirna me ( ) だけメモリ解放が必要かは , Fig. 3 を 見るとわかることでしよう。このように 結果となる文字列をメモリ上に新しく確保 してしまいます。 List7 の使用例では , メモリ配置をわか りやすくするためにポインタの値も表示す るようにしています。 ストップウォッチ機能 便利なストップウォッチ機能を提供して くれる関数群を紹介します ( TabIe 5 ) 。 List 7 に示す使用例を見ていただければ , 一目 瞭然だと思います。 new, des 仕 oy なんてい TabIe 4 gchar* g— TabIe 5 const gcha 「 *file name) : gchar* g_dirname (const gchar *file name) : ストップウォッチ機能を持つ関数 関数名 の誤差が出ると思います。 作させてみると標準出力などの関係で若干 ちなみに , sleep は 3 秒ですが , 実際に動 ね。 記述するとすっきりしそうな感じがします かにもオプジェクト指向的で , C + + 言語で VOid g—timer—destroy (GTimer *timer) : VOid g_timer_ 「 eset (GTime 「 *timer) , gulong * microseconds) : GTimer *time 「 , gdouble g—timer—elapsed ( VOid g_timer_stop (GTimer *timer) : VOid g_time 「 _start (GTimer *timer) : GTimer* g_timer_new (void) : ■ 0 ・ 0 duplicate 説明 バス名の中からファイル名のみを返す バス名の中からディレクトリ名を返す 説明 タイマを作る タイマをスタートさせる タイマを止める 経過時間を得る タイマをリセットする 作ったタイマを破棄する おわりに 次回は GLib が提供するデータ構造の機 能を解説してみたいと思います。ぜひおた のしみに 1 32 C MAGAZINE 2 側 1 6
帳でお困り インターネットで、 伝票印刷 、〕一一できないかなあ ? ナ 十 十 実 C プログラマのための C + + 入門 使われています。 1 つは前の節で出てきた 能を拡張したクラスを作ってみます。 List 2 がそのちょっとだけ機能を拡張したクラ 自動記憶クラスの変数 , もう 1 つは引数を 伴ったコンストラクタです。変数は何らか スのプログラムです。 の目的を持って使われます。 C + + ではその このプログラムには 2 つの新しい要素が 変数自体に機能を持たせるのですから , 引 数のないコンストラクタよりは引数を持っ Fig. A i386 プロテクトモードレジスタ たコンストラクタのほうがずっと使う頻度 31 0 が多いはずです。 List 2 の例では , 単純に 初期化のときに文字列へのポインタを渡し てそれを保持しておくだけの単純なクラス です。 Fig. 2 がその実行結果です (FreeBSD 4.2 ) 。 ちなみに "GlobaI" と。、 cal Static" の初期化 の順番に規定はありません。この例では定 義順になるので , 。、 Global " と "Local Static" の行を人れ替えるとメッセージも入れ替わ ります。ほんの 20 行のプログラムですが , アセンプラソースを出力させると C にはな い c + + 独自の「システム組み込み機構」がた くさん見えてきます。 多少「人門」といった指向から外れますが この 20 行のプログラムから展開される C + + の奥の仕組みをじっくりと検証してみまし よう。 List I にアセンプラソースとその説 明を示します。 List I のコメントのうち # # で始まるものはその行の説明ではありませ ん。また , コンパイル結果のすべてについ てコメントしていません。今回の説明で必 要な部分だけ抜粋しています。グローノヾル Fig. 2 List 2 の実行結果 宅 c 十十 test. cc ー 0 test . /test 引 ob 引 started Local Static started B lock Static started Auto started AutO ended Block Static ended Loca ー Stati c ended 引 0 ー ended 7 1 5 eax ah 0 7 1 5 31 ebx あリシ るボー 」 ! オ bx bh 0 1 5 31 7 eCX CX ch インタ - ネット対応帳票作成ツール ・動作環境 Mic 「 0S0 代・ Windows@ 95 / 98 、 Microsofte Windows NT@ Ve 「 4 十 SP3 以上 Mic 「 0S0 代⑧ Windows@ 2000 ・構成フォームエデイタ、描画コントロール、 ビュアー、ビューコントロール ( オプション ) 、 Ver4. X 互換 DLL ( オプション ) ・描画機能直線・四角形・円・扇・弓・弧・多角形、 ラベル・データフィールド・リストフィールド・ テキストフィールド・バーコードフィールド、ビクチャ、 イメージフィールド OLE オプジェクト ・バーコードの種類 CODE39 、 CODE128 、 JAN8 、 JAN13 、灯 F 、 NW7s 郵便バーコード、 PDF417 ( オプン ) 、 QR コード ( オプション ) ・対応イメージ JPEG 、 BMP 、 D 旧、 WMF 、 EMF 、 T 旧 F ( フォーマットに制限あり ) ※シーオーリボーツは、株式会社工イチ・オー・エスの登録商標です。 ※ Mi 0S0 化 WindOWS. Windows NT は、米国マイクロソフト社の 米国またはその他の国における商標または登録商標です。 株式会社工イチ・オー・エス ・本社 TEL : 052 お 83-7102 FAX : 052-683 ・ 7104 ・東京事務所 TEL : 03 ・ 5789 ・ 2596 FAX : 03 ・ 5789 ・ 2597 シーオーリボーツ無料セミナー開催 ・開催地名古屋本社・東京事務所 ・詳細ホームページをご覧ください。 0 31 7 1 5 edx dx dh 0 31 eSl edi ebp esp シーオーリホーツ V 町 .7 体験版タウンロード・お問い合わせは、 IJRL http:〃 WWW. hos. CO. jp/ E-Mail:info@hOS. CO. jp 実践 c + + ゼミナール 63
メ五ロ ス万第七十八語 一一 = 0 Lisp と Scheme 千 きだあきら まだが , 「関数をⅱ rstclass として取り扱え Lisp の光と影 るかどうか」で分かれるとする見解がある。 プログラミング言語の発展に関して , Li この点 Lisp 1.5 ではどうだったかというと , sp が果たした役割は非常に大きい。 Lisp の 関数は完全なⅱ rst class ではなかった。少な 登場以前は主に数値計算のために使われて くとも 1 つのオプジェクトとして表現でき いたコンピュータを , ツリーやグラフなど るようにはなっていなかった。 Scheme の といった構造を持ったデータや , それを利 第 1 の改良点は関数をⅱ rst class オプジェク 用した記号操作の処理にも使える ( むしろ トにした点であり , それによってまぎれも ない関数型言語になっている点であろう。 そのほうが向いている ) ことを実証したの 少なくとも関数を動的に生成するという観 がこの言語である。 また , Symbolic expression (S-ex , 「 S 表 点では , Lisp 1.5 の能力は Scheme のそれに 現」とか「 S 式」とも呼ぶ ) というデータ表現 は遠く及ばないものである。 を発明し , プログラムもデータも同一のこ 両者の違いの一端は , S 表現の評価にも 現れている。たとえば , 「 (f x y z) 」という S の形式で表現した。これによって , 高水準 言語として初めてプログラム自身を処理す 表現を考えよう。 Lisp/Scheme では , これ るプログラムを簡単に実現した。そしてこ を関数呼び出しとして評価するが , その手 れらの特徴によって , Lisp は人工知能関係 順が少し違う ( ちなみに , 正式な Scheme 用 のプログラミングにおいて幅広く使われる 語では「 procedure ca Ⅱ ( 手続き呼び出し ) 」 表された順序は Lisp 1.5 が最初で , ついで というが , これは言葉の表現だけの問題で ようになった。 別の観点から Lisp の特徴を表すと , 簡素 ある ) 。 Scheme が , それから Common Lisp が登場 でありながらも強力な言語である。言語仕 する。 Common Lisp は Scheme から機能の Fig. 1 に両者の評価手順の基本戦略を示 様はあくまで単純にできている。 Lisp への 一部を取り込んでいるが , 既存の方言との した。もちろん Fig. 1 の定義にはすべての 批判の 1 っとして「ソースの中に登場するカ 互換性を考えた結果 , Scheme に追いつい 評価手順を記してはいない。わかりやすさ ッコが多すぎる」というのがある。しかし のために , 詳細は省略して大枠を示してい ていない部分があることは否定できない。 これは構文が単純であることの裏返しであ るだけである。それでも , Scheme におけ first class function り , そうした単純なパーツを組み合わせる るルールのほうがずっとシンプルであるこ ことにより非常に幅広い機能を実現できて 関数型言語と呼べる条件の定義はさまざ とがわかる。 いるのだ。だが , 実は Lisp にはいくつか手 Fig. 1 「 ( fxyz ) 」の評価順序 抜かりがあったことが指摘されている。そ して , その手抜かりを修正することを目的 (f x y z) を評価するおおまかな順序 ただし f, x, y, z は任意の S 表現とする として誕生したのが Scheme である。 Sche me は見方によっては Lisp の方言の 1 つであ るから , 両者のプログラムソースはカッコ が多く登場するのをはじめとして , 見かけ はよく似ている。しかし一般論としては , Scheme のほうがより単純であり , より柔 軟である。 ところで , Lisp には (Common Lisp を含 めて ) さまざまな方言があるため , 単に Lis p というだけでは今回の議論があてはまる 処理系もあればあてはまらない処理系もあ る。以下では , 基本的に Common Lisp 以前 の古い Lisp 言語を議論の対象としている。 具体的に特定するならば Lisp1.5 にする。発 164 C MAGAZINE 2001 6 ( 1 ) Lisp の場合 (a) 引数 , すなわち x , y, z をそれぞれ評価して引数リストを作る (b) f がアトムであれば . 以下の処理をする (b-l) f が原始関数である ca 「 , cdr, cons, atom, eq の中の 1 つであれば . それに応じた処 理をする (b-2) さもなければ f はユーザ定義関数であるから , その関数定義を取り出して , 引数リスト に適用する (c) さもなくて , f がリストであれば , 以下の処理をする (c-l ) f が (lambda ・・・ ) であれば , それに応じた処理をする (c-2) f が (label••・ ) であれば , それに応じた処理をする ( 2 ) Scheme の場合 (a) f, x, y, z のそれぞれを , ( 任意の順序で ) 評価する (b) f の評価結果に , x, Ⅵ z の評価結果を引数として渡す
最新国ロロレポート Fig. 7 自動生成コードとユーサが入力したコードを区別して表示する コンポーネントインスペクタ 当ソースエデイタ [JFrame コンポーネントインスべりタロンポーネントインスペ・冲 [iT t ” 1 月再同区、 JF 「「ト F 「謝 nel 非表示コンポーネント ? 目 p , 回 1 り 向血 82 ト on ー ロ芦や師に 1 [JS 師 を朝を可 52 53 54 55 58 58 53 62 一 64 ー pub lic static VO nai 宿 (String [ ]) { 間 背 JFrame ( ). 曲 0 背 ( ) : 73 / / 第数第、 - 第第下可 private 」 & & x. ー . JPane ー jParell: 0 ⅱ加」 x. S'* ー . J 社 j & 」社 onl : 73 private ” x ・” i 催・ J j 82 : private j Ⅶ x. i . J ro Ⅱ P & j 新「 0 Ⅱ Panel : private javax ・新i催 . JTextArea jTextAreal; 8 圧 〃第数毅のわり & 2 : 3 jTex 「 1. tFont ( 響 . 羲 . Font ( 第こ覊” 0 , 13 ) ) : jT を気 Area1. 能 t Xt ( " を、 jScrollPanel.ætVie»ortViev(jTextÅrea1); t n n 3 儷 ( ). add ( j 「 0 Ⅱ円し扣 . t. r 礼観 0 . NTER ) : / “日を市 00 */ pri void exi 0 「 j & . ”しを . 引「響印をを ) { Systen. exit い ) : 4 靉定なし、 05 05 ロ如 ■わ地 k 9 0 にエ TION ロい 53 , 1533 F 50 T れ肥 ロ Monos aced 18 、準 ■ bbck 、設定なし プロバテ また , 自作の JavaBeans コンポーネントを フームエデイタと イベント処理の定義 パレットに追加することも可能だ。 コンボーネントインスペクタ フォームエデイタはソースエデイタと連 イベ コンポーネントインスペクタでは , ントハンドラの定義も行える。イベントの 係している。フォームエデイタ上で GUI コ Forte ではソースエデイタによるコーデ 種類を選び , ハンドラを定義すると , イベ ンポーネントを配置すると , 対応する初期 イングに加えて , グラフィカルなツールに ントハンドラの登録処理とイベントハンド 化コードなどが自動的に挿人される。この よるユーザインタフェイス構築も可能であ ラのメソッド宣言が自動的にソースコード ように自動生成されたコードは , ソース工 る。このためのツールがフォームエデイタ に追加される。ユーザは , ソースエデイタ デイタで陰影を付けて表示され , ユーザが (Fig. 5 ) とコンポーネントインスペクタ (Fi を用いてイベントハンドラの内容を記述す g. 6 ) だ。 GUI コンポーネントを配置するた 入力したコードと区別できるようになって るだけで済む。 いる (Fig. 7) 。 めにはフォームエデイタを使用する。一方 , イベントに関しては , 接続ウイザードと Forte では , 自動生成コードをソース工 配置した GUI コンポーネントを階層的に表 いう支援機能がある。イベントの発生元と デイタで変更することができない。フォー 示したり , 各コンポーネントのプロバティ なるコンポーネントと , イベントに対する ムエデイタで生成したコードをユーザがソ を操作したり , イベント処理を定義するに 処理を行うコンポーネント , および処理内 ースエデイタで変更すると , フォームエデ はコンポーネントインスペクタを用いる。 容となるプロバテイやメソッドを , ウイザ イタから適切に扱えないコードになる危険 GIJ ロンホーネントの配置 ード / フォームエデイタ上で選択すること 性があるからだ。このような危険性はすべ によって , 対話的にイベント処理が定義で ての Java 統合開発環境が抱えている問題で フォームエデイタは , コンポーネントパ あるが , Forte では自動生成コードとユー きる。 レット上に一覧表示されたコンポーネント ザが入力したコードをソースエデイタ上で の中から任意のものを選択して配置できる。 明確に区別することにより , 危険を回避し コンポーネントパレットには , AWP/Swin ている。コード編集の自由度はやや損なわ g / レイアウト /ポーダ—/JavaBeans の各コ れるが , 自動生成コードを保護するうえで ンポーネントがあり , JDKI. 3 で使用でき る標準的なコンポーネントを網羅している。 は効果的である。 ブジェクトブラウザ オプジェクトプラウザは , オプジェクト を階層的に閲覧するためのウインドウであ 最新開発環境レポート Forte for Java 2.0 Community Edition 155