プログラミング所感 - 前へ 目次 次へ99/1/18(月)とうとう 1999 年である。 また、1ヶ月ぶりの更新。この前買った、「プログラミング言語C++第3版」は 結構、面白い。いろいろな話題がある。例えば、 void fc(char&){} void fi(int&){} int main() { signed char sc; unsigned char uc; signed int si; unsigned int ui; fc(sc); // (1) fc(uc); // (2) fi(si); // (3) fi(ui); // (4) }この中で、どれがエラーになるかわかるだろうか? 答えは、(3)以外全部である。 char が signed か unsigned かは処理系定義である。int は、signed である。 従って、正しい呼出しは、(3) だけである。 なになに、「(1) か (2) のどちらかは正しい筈だ」って? 確かに、VC++ では char は signed である。でも、VC++ で fc(sc); はエラーだ。 他の処理系に持っていって始めてエラーになるよりは、予めエラーになっている方が いいに決まっている。 結局、char は 3種類あるが、int は 2種類しかないのだ。 つまり、「signed int」と書く必要は全くない。 ちなみに、上のプログラムで main に return を書かなかったのは わざとである。理由は、件の本の§3.2 を見て欲しい。 99/1/20(水)私的派生と限定派生について思ったこと。私的派生と限定派生は、実装の継承として用いられるようである。 これは、私的メンバや限定メンバを持つようにしても実現できる。 私的(限定)派生するのとメンバに持つことの違いは以下の点を除いて殆どない。
この例では、D2 の方が D1 よりオブジェクトのサイズが、
仮想関数テーブルのポインタ(以下、vfptr)1つ分大きくなる。
これは、D1 が vfptr を1つしか持たないのに、D2 は2つ持つからである。
この例では、pv->test() は、正しく機能するが、p->test() は機能しない。 何故なら、typeid は仮想関数を持つクラスでないと利用できないからである。 結局、私的(限定)派生であれ、派生に伴う制約を受ける。 例えば、複数の機能を利用する場合、派生で実現しようとすると多重継承になり兼ねない。 従って、派生よりはメンバで実現した方がすっきりするといえる。 私的 or 限定派生を使う必要はないと思う。 99/3/3(水)オーバロードとスコープの関係について誤解していた。
例としては、
今まで、f(1) は OK と思っていた。 結論 − オーバロードされている関数群の1つでも派生クラスでオーバライドしたら 全てオーバライドし直さなければいけない。(using B::f; などとしてもよい。) 99/5/24(月)最近、忙しくて3ヶ月ぶりくらいの更新だが、 内容はたいした話しではない。 この前、デバッグしていた時のことであるが、結果がおかしいので、 常に整合性を見るようにし、おかしくなった時点で、すぐ判るようにした。 で、判ったら、その条件になったら止まるようにして、もう一度動かすのだが、 そうすると、そこではおかしくならずに違う所でおかしくなるのだ。 その条件で止まるようにしても、また別の所に移ってしまう。不確定性定理みたいに見ようとしても見えない。 デバッガのブレークポイントを変えただけで、結果が変わってしまうのだから わけがわからない。結局、バグは取れたのだが、原因は良く分からないままである。 99/6/16(水)条件チェックのスピードを比較してみた。x が x1とx2の間に入るかどうかを調べたいとする。 但し、x1 < x2 かどうかはわからない。方法としては、次のように2つ考えられる。
私は、(1)の方が分かり易くて好きだが、VC++でスピードを測ると (2)の方が、30%ぐらい速い。 しょうがない、(2)で書くことにしよう。 細かいことを言えば、(2)では、最大4回比較を行う可能性がある。(x1 == x, x2 < x) 次のように書けば、最大は3回で済む。
最初の ! をとれば、次のように書ける。
これより次の様に書く方が比較回数が減る可能性がある。
全部計測してみたが、(1)以外はどれもスピードは変わらなかった。 99/6/17(木)この前、歯医者の予約をすっぽかしてしまった。で、スケジュールを忘れないように、指定時刻にメモが出るような ちょっとしたアプリを作った。Windows98 や NTなら、タスクマネージャでできるし、 UNIX なら at でできる。そろそろWindows98に変えてみようかな。 99/6/22(火)ちょっと思ったこと。 オブジェクト指向風にプログラム書いていくと、「これは、アンタに任すわ」 っていうような、自分で何もせずに仕事を振り分けてるだけのクラスとか よく作っちゃうような気がする。で、いろいろなクラスの間を取持つ役目に なるんだけど、何かいい身分だよな。 話は変わるけど、自分のプログラミングの癖を見つけた。 99/6/25(金)MS 特有の機能に失敗した。 min,max を使っていたら、どうもおかしい。 ヘルプを見ても、テンプレートなのに副作用がある。で、やはりマクロだった。VC++ では、min,maxが3種類もあった。
99/7/19(月)配置車両のデータ構造をどうすればよいか悩んだ。最初は、単純に1個所で保持していた。(1) 配置データは主に、
ところが、このままだとスロープ上の車両が問題になる。 スロープ上の車両は複数デッキで見える可能性があるからだ。 かといって、スロープ上の車両は見えるデッキに冗長に持たせるのも 整合性がくずれやすい。そこで、スロープ上の車両は、デッキに持たせるのではなく 船に持たせるようにした。(3) このとき、今まで別のクラスで管理していた「コピーやUNDOバッファ」用の データを都合上、配置データに合併させた。(構成が同じなので。 別のままだと、構成が一致するように気をつけていけない。) しかし、このことにより同じ配置データをデッキと船の2個所で管理するのが 不便になった。そこで、配置データをまとめて管理するクラスを作成した。(4) これでも、スロープ上のデータは、デッキ毎に参照されるので、 1つのデータをデッキの数だけチェックされる。 結局、デッキで表示されるべき車両は、デッキ上かスロープ上かに関わらず、 同じようにアクセスできるようにした。(vector<CPlace*>として) このため、配置データをデッキ及びスロープで持つことにした。(5) なぜ、始めからそうしなかったかは聞かないで欲しい。 99/7/21(水)今日、見つけた VC++6.0 のバグ
コンパイルエラーにならない!g++ はなるぞ。 99/7/23(金)今日、見つけた VC++6.0 のバグ第2弾
コンパイルエラーにならない!g++ はなるぞ。 99/9/8(火)参照メンバ変数について。メンバに参照変数があると、デフォルトでは代入演算子が作られない。 これは、正しい仕様に思える。 実際のところ、「参照メンバ変数は、可能だが使うことはない」と思っていた。 ところが最近、人の書いたソースで次のようなのを見た。
最初、何だこりゃと思ったものの、よくよく見ると正しいし、理にかなっている。
恐らくこれが唯一の参照メンバ変数の正しい使用法だろう。
こうすれば、代入演算子も定義しなくて良いから、よけいなものを書かなくて済む。
まぁ、今のままの仕様の方がすっきりするけど。
99/9/9(水)代入とswap の速度は、どちらが速いか?次のコードで考えてみて欲しい。
もし、代入後の j の値を使わなければ、(1) でも (2) でもよいはずだ。 違いは、代入ではコピーコンストラクタが呼ばれるのに対し、 swap では、呼ばれないという所だ。だから、swap の方が速いと思われる。 実際に計ってみると、XXX が int では、代入の方が速いようである。 何故だかよくわからない。 今日は、9並びの日だ。そう言えば、一昨年は年号が9だった。 99/9/20(月)カーソルの表示について。 OnSetCursor で、モードに応じてカーソルの 表示を変えていたのだが、最初の1回は変わるのだが 別のモードにしても変わらないことがあった。 特徴的なのは、起動直後モードAにすれば、 カーソルもAになるのに、モードBにしても 変わらない。また、起動直後モードBにすれば、 カーソルもBになるのに、モードAにしても 変わらないことだ。結局、半日かかって原因は分かった。 LoadCursor でカーソルを作るとき、絵のビット情報から あるハッシュ値を作っているようだ。それで、そのハッシュ値で カーソルの同一性を判断しているらしい。従って、絵が似ていると 同じカーソルと判断されてしまう。結局、回避するために 絵をずらしたりして変更せざるを得なかった。99/11/1(月)MFC の GDI オブジェクトについて。 リソースがリークしていて原因を調べたら、 CDC::SelectObject で選択していた GDI オブジェクトを DeleteObject していたせいだった。99/11/22(月)Java の話である。 C++ の所感であるが Java の話をちょっと。 Java に関する備忘録的なページをJAVA One Pointにまとめた。 この中で、電卓のサンプルが作ったのだが、 疑問がいろいろでてきた。
99/11/24(水)C Magazine の記事を読んでたら、 前に一度書いたこと と同じようなクラスを作っている記事があった。しかし、参照カウント付き配列用クラスも、別クラスとして作っていた。記事の作者は、STL の本書いているくせに、センス悪いね。前へ 目次 次へ |