読者です 読者をやめる 読者になる 読者になる

ゆとりーなの日記

日記的な事を書いて行くと思はれる

そのあと対面が字一色アガった

この間の自己代入のコードが載ってた本です。

すべてのプログラマに効く 危険なプログラムの処法箋
すべてのプログラマに効く 危険なプログラムの処法箋宮坂 電人

ソフトバンク クリエイティブ 2007-03-29
売り上げランキング : 595677

おすすめ平均 star
star現場によくあるアンチパターン
starもう少し安ければ買いたい
star問題指摘に関しても80%しか同意できない…

Amazonで詳しく見る
by G-Tools
C++独自の落とし穴という項目があるのですが、Cプラー駆け出しの頃には結構役に立つなとか思っていたのですが、今見ると???な感じの指摘がちらほら見られたりするのでそこらへんを。

オブジェクト指向に於いては全てのメンバ関数は仮想であるべき

メンバ関数を仮想にするとコストがかかるからデフォルトを仮想にしないのは変という指摘です。確かに仮想でない関数をオーバライド(っていうのか怪しいですけど)したときの悲劇とかを考えると一理あるといえばあるのですが、テンプレート等で静的多態が実現できたりと動的多態に頼らない場面が結構あるので、仮想をデフォルトにすると、そこいらにコスト面で迷惑になります。デフォルトを逆にするにしても、個人的には仮想にしたい場合の方が圧倒的に少ないと思うので現状のままで問題はないと思います。

基底クラスのpublicメンバを隠すべき

public継承した際、特定のメンバ関数をオーバーライドするつもりもなく使用禁止にしたい場合はprivateメンバにして実装を省略することで達成できるとあります。著者の方的にも、この解決策はあまりいいと思っていないみたいなのですがあんまり知られていない豆知識的なノリで載せたみたいです。しかしこのようなpublic継承に喧嘩を売っている設計方針を知る必要は全くないです。そもそもこのような場面にpublic継承を使うことが間違いであり、因ってこのようなテクニックを使う場面はありません。

暗黙のメンバ関数を定義すべき

コピーコンストラクタと代入演算子は、メンバ変数にポインタがあった場合ちゃんと定義しましょうという話です。まあ定義しなければいけない場面が全くないとは言いきれませんが、ここに載ってる例で言えば、文字列を格納するバッファとか言うくらいなら大人しくstd::string使えばいいですし、大抵のポインタの扱いはスマートポインタを使ってやれば、コピーコンストラクタと代入演算子を定義してやらなければいけない場面は稀です。因にstd::unique_ptrを使う場合は、代入演算子を消しておかないとコンパイラが怒るみたいです。

仮想関数を嫌う人を嫌う

本の中で、仮想関数を避ける人たちの理由として二つ挙げられています。

  • 仮想関数というのがよく分からないから使わない
  • 仮想関数のコストが気になるから使わない

一個目の方は論外としても、二個目の方は果たしてdisられる対象なのでしょうか。本当にコストがさけられないものなのかを調べるべきとありますが、C++では仮想関数を使わなくてもテンプレートを使えば同等のことができるので仮想関数を使わないというスタイルも全然アリだと思います。

delete関連の話

deleteにまつわる落とし穴として、二重deleteの問題や不定値でdeleteの問題が挙げられていますが、そもそもdeleteが普通のC++コードに出てくることが問題です。ここの解決策は大人しくスマートポインタを使いましょうでいいのです。

コンストラクタは例外を外に漏らさないべき

これはC++独自の落とし穴ではなく例外の使い方の項にあるのですが、コンストラクタから例外が漏れるとデストラクタが呼ばれないという現象を過剰に恐れている感があります。対案として、コンストラクタ内でtry-cathcするとか、別途初期化関数を用意するというのが挙げられています。デストラクタが呼ばれないのを恐れる主な原因としては、デストラクタでリソースの開放を普通のクラスで行うという習慣が染み付いているからです。リソースの管理はそれ専用のクラスが行うべきであり、確かにそれら管理クラスはコンストラクタで例外を投げてはいけないと思います。しかし普通のクラスでは、リソース管理は全てそれら管理クラスに任せるので、デストラクタが呼ばれなくてもメンバ管理クラスのデストラクタが呼ばれればいいわけですから特に問題はないのです。というかデストラクタを書かなければいけない場面にはそうそう出会いません。