1

設計中に、仮想メソッドを追加/削除する状況が発生することがあります。私が知っている経験則は、仮想メソッドを取得したら、仮想デストラクタを使用することです。

私の質問:クラスを作成するときに仮想デストラクタをすぐに追加した場合(仮想メソッドがまだない場合でも)、害はありますか?基本的には、後で忘れないようにするのが目的です。特にn個の派生クラスでは、後でn個の場所で変更する必要はありません。

4

5 に答える 5

5

仮想関数テーブルのサイズにはわずかなオーバーヘッドがあります。おそらく心配する価値はありません。仮想デストラクタは、クラスを非集約、非自明クラス、非標準レイアウトクラス、したがって非PODクラスにします。手元の問題によっては、これは望ましくない場合があります。

ただし、クラスを多態的であるかどうかを明確に設計することをお勧めします。多態的に使用する場合は、仮想デストラクタを提供します。そうでない場合は、しないでください。変更する必要がある場合は、必要なときに変更してください。

于 2013-03-24T11:43:07.693 に答える
1

唯一の害は、クラスとすべての派生クラスに、サイズがわずかに増加するvテーブルがあることです。後で基本クラスのデストラクタを仮想化することにした場合でも、派生クラスに変更を加える必要はありません。デストラクタを含むすべてのメソッドでは、仮想キーワードを1回だけ使用する必要があります-基本クラスで。派生クラスの同じメソッドは自動的に仮想になります。

別の方法として、デストラクタを保護することができます。これにより、基本クラスのポインタを使用して誤って削除が呼び出されるのを防ぐことができます。

class A
{
    protected:
    ~A(){}
};

class B : public A
{};

int main(int argc, char *argv[])
{
    A * p = new B;
    delete p;
}

私のコンパイラでは、次のエラーが発生します

エラーC2248:'A ::〜A':クラス'A'で宣言された保護されたメンバーにアクセスできませんa.cpp(9):コンパイラが' A ::〜A'を生成しましたここでa.cpp(6):'の宣言を参照してくださいA '

于 2013-03-24T11:41:04.703 に答える
1

いいえ、他の仮想メソッドがない場合でも、仮想デストラクタを使用することは完全に理にかなっています。

ただし、メモリ使用量が重要な場合は、すべてのバイトが重要であり、仮想メソッドがない場合は4バイトまたは8バイトを取得できます。私のアプリケーションには、何百万ものインスタンスがあるクラスがいくつかあります。その場合、クラス内のvポインターを取り除くことは本当に理にかなっています。

デストラクタを非仮想から仮想に(またはその逆に)変更する場合に、派生クラスを変更する必要がある理由を完全には理解していません。メソッドが仮想になると、仮想を指定しなくても、すべての派生クラスで同じメソッドが仮想になります。それでも、スタイル上の理由から、必要がない場合でも、派生クラスに仮想を追加することをお勧めします。

于 2013-03-24T11:46:12.220 に答える
1

やみくもにルールに従わないでください。つまり、ルールに従いますが、盲目的にそれを行わないでください。

仮想デストラクタが本当に必要な場合は、オブジェクトがそのベースオブジェクトポインタを介して削除される場合のみです。経験則では、この条件を一般化して単純化します。オブジェクトがそのベースオブジェクトポインタを介して削除される可能性がある場合、そのオブジェクトは多形的に使用されます。ポリモーフィックオブジェクトは仮想関数を持っている可能性が高く、仮想関数を持っているオブジェクトはポリモーフィックに使用されている可能性があります。したがって、仮想関数を持つオブジェクトには、仮想デストラクタが必要になる可能性があります。

これはすべて問題なくダンディであり、ルールはほとんど機能しますが、そのようなルールが実際に機能することもあり、めったに言及されない、より重要でより基本的な事実があります。実は、値のようなオブジェクトと、名前がよくない他の種類のオブジェクトがありますが、私はそれらをエンティティのようなオブジェクトと呼びます。エンティティのようなオブジェクトは、値とは別のIDを持ち、参照セマンティクスを使用します。正当な理由(別のIDの作成など)なしにコピーしないでください。多態的にアクセスされる可能性があります。値のようなオブジェクトにはIDがありません。それらの価値に加えて、それらは自由にコピーすることができます、それらは多形的に使用されるべきではありません、など。それらは非常に異なるので、それらのクラスに異なるキーワードを持つ価値があります!クラスを設計するときは、クラスがどのカテゴリに属する​​かを決定する必要があります。その後、あなたの質問はそれ自体で解決します。エンティティは仮想デストラクタを取得しますが、値は取得しません。

于 2013-03-24T12:08:13.047 に答える
0

仮想デストラクタを使用する唯一の理由は、派生型のオブジェクトを基本型へのポインタを介して削除できるようにするためです。それがクラスの設計で求められているものである場合、他の仮想関数がなくても、仮想デストラクタが必要です。デザインにベースへのポインタによる削除が含まれていない場合は、仮想関数がある場合でも、仮想デストラクタは必要ありません。ベルトとサスペンダーの人々は、とにかくデストラクタを仮想化するようにあなたに言うでしょう、なぜならそれは何も傷つけないからです、そしてまあ、あなたは決して知りません。これは技術的な理由ではありません。これは、ドキュメントを読んだりフォローしたりしないユーザーから保護するためのポリシーの選択です。

于 2013-03-24T12:36:43.050 に答える