メインコンテンツ

基底クラス デストラクターが非バーチャル

派生クラス オブジェクトの削除にあたりクラスがポリモーフィックに動作できない

説明

この欠陥は、クラスに関数 virtual はあるが、virtual デストラクターがない場合に発生します。

リスク

virtual 関数の存在により、そのクラスは基底クラスとしての使用が想定されていることが示されます。しかし、クラスに virtual デストラクターがない場合は、派生クラス オブジェクトの削除にあたりポリモーフィックに動作できません。

このクラスを指すポインターが派生クラス オブジェクトを参照し、ポインターを使用してオブジェクトを削除する場合、基底クラス デストラクターのみが呼び出されます。派生クラスに割り当てられている追加リソースは解放されず、リソース リークの原因となることがあります。

修正方法

1 つの修正方法として、virtual 関数を含むクラス内の virtual デストラクターを常に使用します。

すべて展開する

class Base {        
        public:
                Base(): _b(0) {};
                virtual void update() {_b += 1;};
        private:
                int _b;
};

class Derived: public Base {                     
        public:
                Derived(): _d(0) {};
                ~Derived() {_d = 0;};
                virtual void update() {_d += 1;};
        private:
                int _d;
};

この例では、クラス Basevirtual デストラクターがありません。したがって、Base* ポインターが指す Derived オブジェクトにメモリが動的に割り当てられていて、delete 操作がその Base* ポインターで実行される場合は、Base デストラクターが呼び出されます。追加メンバー _d に割り当てられているメモリは解放されません。

欠陥は、基底クラス定義に表示されます。ソース コード内での移動のヒントを以下に示します。

  • 基底クラスから派生したクラスを検索するには、基底クラス名を右クリックして [すべての参照を検索] を選択します。各検索結果を参照し、派生クラス定義を見つけます。

  • 派生クラス オブジェクトを指す基底クラスへのポインターまたは参照が使用されていることを確かめるには、基底クラス名を右クリックして [すべての参照を検索] を選択します。Base*Base& で始まる各検索結果を参照し、基底クラスを指すポインターまたは参照を見つけます。これにより、派生クラス オブジェクトを指すためにポインターと参照のいずれを使用しているかを確認できます。

修正 — 基底クラス デストラクターをバーチャルにする

1 つの修正方法として、クラス Basevirtual デストラクターを宣言します。

class Base {        
        public:
                Base(): _b(0) {};
                virtual ~Base() {_b = 0;};
                virtual void update() {_b += 1;};
        private:
                int _b;
};

class Derived: public Base {                     
        public:
                Derived(): _d(0) {};
                ~Derived() {_d = 0;};
                virtual void update() {_d += 1;};
        private:
                int _d;
};

結果情報

グループ: オブジェクト指向
言語: C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: DTOR_NOT_VIRTUAL
影響度: Medium

バージョン履歴

R2015b で導入