ブログトップ 記事一覧 ログイン 無料ブログ開設

神様なんて信じない僕らのために このページをアンテナに追加 RSSフィード

2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
基本的に適当な日記です。あまり鵜呑みにしないでください。土日はWeb離れしているので反応遅れます。

2008-09-25

[]ある程度経験を積んだC++プログラマは絶対にvirtualデストラクタのないクラスを継承しない?

ある程度経験を積んだC++プログラマは絶対にvirtualデストラクタのないクラスを継承しない

C++では基底クラスにvirtualデストラクタを書こう - *「ふっかつのじゅもんがちがいます。」withぬこ

はよくある間違い。あるいはC++初心者の勘違い。

継承する可能性のあるクラスにはすべてvirtualデストラクタを作る

C++では基底クラスにvirtualデストラクタを書こう - *「ふっかつのじゅもんがちがいます。」withぬこ

ということが否定されていることは言われるようにEffective C++を読んでいればわかること。

C++では、コピー不可にするために以下のようなクラスを書いたりするが、

(コピーコンストラクタとコピー代入演算子を無効にする)

class Uncopyable {
protected:
    Uncopyable() {}
    ~ Uncopyable() {}
private:
    Uncopyable(const Uncopyable&);
    Uncopyable& operator=(const Uncopyable&);
};

こうしたクラスは継承に使われるが、仮想デストラクタを宣言することはない。

これらは、

class Hoge : private Uncopyable {
public:
    Hoge(int value) : value_(value) {}
private:
    int value_;
};
// こうすると、
Hoge hoge1(1);
Hoge hoge2(hoge1);  // コンパイルエラー
hoge2 = hoge1; // コンパイルエラー
// になる。

codepadで実行してみる(コンパイルできないよ版)<-真似してみた

codepadで実行してみる(コンパイルできるよ版)

このように使われることを想定しているため、

Uncopyableは

空の基底クラスの最適化を期待するために「仮想デストラクタでないことが望ましいクラス」で

かつまた、「継承されることを目的としているクラス」です。

故に「絶対に」は言い過ぎです。

しかも、これらのことはEffective C++に書いてあります。


多くの場合、仮想デストラクタに関しては、

  • ポリモルフィズムをするための基底クラスには仮想デストラクタを持たせよう。特に仮想関数を持つクラスは必ず仮想デストラクタを持たせよう。
  • 継承を目的としていないクラス、または継承を目的としていてもそれがポリモルフィズムを目的としないのならば仮想デストラクタを宣言すべきではない。

となると思います。

C++ FAQ.より

実用的で簡単かつ憶えやすい指針を紹介しよう。

「あるクラスが仮想関数を持つならば、仮想デストラクタが必要になる。これに対して、クラスが全く仮想関数を持たないならばそのクラスが基底クラスとなる予定はないという設計なのだから、仮想デストラクタは不要だ」

とあります。

が、続けて

ただし、この指針がすべての環境下で適応できるほど正確でないことに注意しよう。

正確なルールは憶えるのがとても難しい代物なのだ。

ちなみに、これよりも正確なルールを紹介しよう。

「どのような派生クラス(もしくは、データメンバかつ/または(and/or)派生クラスの基底クラス、あるいは、派生クラスのデータメンバのデータメンバの基底クラス、あるいは、派生クラスのデータメンバの基底クラスと基底クラスとデータメンバの再帰的な組み合わせすべて)は、何らかの意味を持つデストラクタを持ち(あるいは、持つだろう)、そして、どこかに存在するコードが基底クラスのポインタを使って派生クラスを削除する可能性があるならば、基底クラスのデストラクタがvirtualである必要がある」

なにをいっているかわからねーと思うが

要するにC++はめんどくさいということだ。

やれやれ!

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証