kbcl0のページ#1
(4) 開発日記#1
- 2019.04.27(土)
- [1] とりあえずC++に切り替えたらどこまでできるかに挑戦。C++にはコンストラクタがあるので、初期化のための関数呼び出しを書く必要がないので、これは節約できそう。さらにデストラクタもあるので、解放処理も書かなくていい。おおこれはすごい。やる前から理屈ではわかっていたけど、いざ実際にオブジェクトを宣言しただけでコンストラクタが確実に呼ばれて、変数スコープから抜けるだけでデストラクタが呼ばれるので、なんかびっくりするほど簡単に感じる。・・・そうかー、C++が大好きでいつも使っている人はこんな世界で暮らしていたのかー。すごく甘やかされている感じがするけど、確かにこれは慣れたらやめられないかも・・・。
- [2] kclib1のときは「初期化忘れがないかチェックするコードを入れるかどうかで、デバッグモードとリリースモードを用意していたのだけど、もう初期化忘れは基本的に想定しなくてよくなったので、チェックするコードはいらなくなって、シンプルになった。
- 2019.04.28(日)
- [1] このkbcl0では「積み上げ」型の開発を指向しているわけだけど、そうするとクラスの依存関係は当然かなり出てくる。例外なく、先に作ったものから順番に準備していけば破綻はない(=開発するときに未来の開発物を必要とするような書き方はしていない)のだけど、しかしそれでもグローバルスコープにオブジェクトを置こうすると、C++ではグローバルスコープのオブジェクトのコンストラクタの呼び出し順序に関する保証が何もないので、準備しておいてほしい下位ものがまだできていないのに上位のコンストラクタが呼び出されるという、ややこしいことが発生した。
- これを回避するために以下の処置をとった。
- (1)まずクラスを継承してstartup対応クラスを作る。
- (2)このstartup対応クラスでは、コンストラクタが複数回呼ばれるかもしれないことを想定し、最初の一回だけ親クラスのコンストラクタを呼び出すようにする。・・・startup対応クラスを作る必要があるのは、コンストラクタを上記のように書き換えることに対応するためである。・・・startup対応クラスは例外なくstatic領域に置かれるので、起動時にすべてのフィールドが0になっていることが保証される。したがって最初の呼び出しかどうかを確認するのはとてもやさしい。
- (3)さらにstartup対応クラスのコンストラクタでは、自分より下位のオブジェクトが初期化済みかどうかを確認する処理を入れる。もし初期化が終わっていないようなら、replacement newの構文を使って下位のオブジェクトのコンストラクタを呼び出してやる。
- (4)もちろんこれをデフォルトの動作にしてしまえば、わざわざstartup対応クラスなど作る必要はなくなるが、しかしそうすると毎回コンストラクタの処理に時間がかかるようになる。しかもヒープやスタック上のオブジェクトは初期化前にすべてのフィールドが0になっているという保証がないため、初期化済みかどうかを判定するのが難しく、簡単な方法で処理した場合、運が悪いと一度も初期化できなくなるという可能性がある。だからstartup対応クラスを作るのが一番手っ取り早い。
- これはめんどくさいなーと感じたけど、でもまあC言語に戻りたいと思うほどではない。全然そんな風には思わない。
こめんと欄