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

C++ Coding Standardsはどう述べているか、という蛇足

egtraさん曰く。(コメント欄

これに限らずデストラクタが非virtualな多態的に使うつもりはない基底クラスはコンストラクタ・デストラクタをprotectedにするのがよい(そしてunary_functionもそうすべきだった)ということは確かC++ Coding Standardsに書いてあったと思います。

std::unary_functionの存在意義がよくわからなくなった。 - *「ふっかつのじゅもんがちがいます。」withぬこ

調べてみた。

50. 基本クラスのデストラクタは public 仮想か protected 非仮想にする
削除すべきか、否か。それが問題だ:基本クラス Base へのポインタを介した削除を許す場合は、Base のデストラクタを public 仮想にしなければならない。それ以外の場合は、protected 非仮想にする。

なるほど。

「あらゆる基本クラスのデストラクタは仮想関数でなければならない」という旧式のコーディング標準が全面的に強いられてきた。
これは(たとえよくあるケースだとしても)やり過ぎである。
その代わり、「基本クラスのデストラクタは、 public の場合のみ仮想関数にする」というルールに置き換えるべきだ。
基本クラスを作成するのは、抽象を定義するためだ。抽象を構成する各メンバー関数に対し、以下の決定をしなければならない。

  • 仮想的に振る舞うべきかどうか。
  • Base ポインタを使用するすべての呼び出し側から public に利用できるようにするか、あるいか、隠蔽された内部実装の詳細とするか。

...
基本クラスのデストラクタに対し、Base ポインタを介して仮想的に呼び出すことを許すか、まったく許さないかの選択になる。
「非仮想に呼び出す」という選択肢はない。
基本クラスのデストラクタは、呼び出すことができれば(つまり public であれば)仮想で、そうでなければ非仮想である。

要するに我々が通った道は既に誰もが悩み苦しみ踏破している道であるということ。

例外事項

次のような希なケースも考えておこう。

  • Base は、基本クラスと、単独でインスタンス化できる具象クラスの両方で使われる。(B オブジェクトを生成、破壊するためにはデストラクタがpublicでなければならない)
  • Base は、仮想関数を全く持たず、ポリモルフィックに使われる意図もない(したがって、デストラクタは public だが、仮想である必要はない)

...
このような希なケースでは、デストラクタを public 非仮想にしても良いだろう。
しかし Base から直接あるいは間接に派生するオブジェクトが Base なポインタを使ってポリモルフィックに削除したりしないよう、明示的に文書化しておくことだ。実際、std::unary_functionではこれが行われている。
しかし、通常は、具象基本クラスを避けよう。たとえば、 unary_function は、単独で初期化されることを全く意図していない typedef の集合である。これに public デストラクタを与えるのは全く意味がない。本項目のアドバイスに従い、デストラクタを protected 非仮想にする方が設計としては優れているだろう。

そして、やはり例外事項があるということ。

関数オブジェクトは、関数ポインタをモデルにしており、関数ポインタと同じく慣習的に値で渡される。
標準アルゴリズムはオブジェクトを必ず値渡しする。あなたの自作アルゴリズムもそうすべきである。
関数オブジェクトはコピーの負荷が軽く、かつモノモルフィックでなければならない(スライス対策のため、仮想関数を避ける)。

Pimplイディオムを使うなら、ポリモルフィックでも構わないと後に続く。

やっぱり、薄いけどよくまとまっていて良い本だね!

C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series)

C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in‐depth series)

  • 作者: ハーブサッター,アンドレイアレキサンドレスク,浜田光之,Herb Sutter,Andrei Alexandrescu,浜田真理
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2005/10
  • メディア: 単行本
  • 購入: 18人 クリック: 311回
  • この商品を含むブログ (96件) を見る