Entry

デストラクタを仮想にすべきか問題について解決(ネタ)

2011年04月18日

デストラクタを仮想にすべきか問題について,「virtual つけたら遅くなるべさぁ!継承する気もないのにんなことする奴ぁ腹切って死ね!」(←誇張)とゆ方がいらっしゃる。で,一方,「んだども,万が一継承されてポリモーフィックに使われてしまったら,リソースが漏れてしまうべさ!んなあぶねぇクラスは公開できねっ!てめこそ腹を切れ!」(←誇張)とゆ方もいらっしゃる。「んな継承はアホな初心者がやることだっ!自業自得だべっ!」「なにおぉー!てめっ!今アホっつったな!」とかとか……(←全部誇張)。

あたしゃ,基本的に公開されているクラス(構造体)のデストラクタは全て仮想にすべきだと思っているんだけれども(継承されると危ないクラスはなるべく公開しない),どちらの言い分も分らなくもない。また,全てのクラスを把握できるほどの小さなプログラムや,ローカルの開発環境で完結してしまう(自分さえ気を付けていればいい)プロジェクトでこんな話を持ち出すのは,それ自体アホくさいとも思う。

ただ,デストラクタを仮想にしない場合,コメントに「継承しないでね♥」と書いたり「デストラクタが仮想になってないのに継承するやつはアホ」と結論付けたりするのは,身内だけに通じるローカルルールに従って言っているだけなので,処理系に基礎づけられた対策になっていないのは確かです。アホと呼ぼうが馬鹿と呼ぼうが初心者と呼ぼうが,言語仕様上許可されている実装なんだから,継承されるときはされちゃいます(そしてそんな諍いについて何も知らないエンドユーザの手元でリークする)。

C++0x では継承を禁止する final を付けられそうなので,近いんだか遠いんだか分らない将来,この問題は過去の話になりそうだけれども,それじゃ,現在もっぱら使われている C++03 以前の処理系ではどうすりゃいいの?となる。で,小ネタ。

どうしても vftable を作りたくなく,かつ継承に対して(コンパイラが検知できる形で)安全なクラスを作りたいのなら,こんなラッパーでくるんでしまったらどうだろう。

union foo {
public:
  foo();
  foo(const foo& other);
  ~foo();
public:
  foo& operator=(const foo& rhs);
public:
  // operations with object inner_ ...
private:
  // struct body
  struct inner {
  public:
    inner();
    inner(const inner& other);
    ~inner();
  public:
    inner& operator=(const inner& other);
  public:
    int a_;
    int b_;
    int c_;
  } inner_;
};

人呼んで,Pseudo Final Class Pattern(今ここでつけた(少し変えた))。テンプレートにすれば,内部クラスについて Policy 的なこともできるよ!

「関数呼び出しのコストがかかるべさぁ!」とか「初期化しづらいやんけぇ!」とか聞こえてきそう……。ま,ネタなので。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN