2012-03-28 8 views
7

仮想デストラクタを持たないクラスから継承すべきではないと私は常に聞いてきました。このルールは多態性を使用したくない場合でも適用されますが、すべてのクラス機能が必要なだけで、さらにいくつか追加したいのですか?具体的には、以下のクラスは、ポリモーフィックに使用しない限り、明確な振る舞いで安全ですか? (派生オブジェクトに、すなわち無消去ベースポインタ)仮想デストラクタを持たないクラスから継承する

template<typename T> 
class SomewhatSafeVector : public std::vector<T> 
{ 
public: 
    typedef std::vector<T> base; 

    T& operator[](unsigned n) { 
     if (n >= base::size()) 
     { 
      throw IndexOutOfBounds(); 
     } 
     return base::operator[](n); 
    } 
}; 
+1

大丈夫かどうかは気にしないでくださいが、標準ライブラリのコンテナから派生するべきではありません。さらに、境界内で動的コンテナにアクセスする際に問題がある場合は、大規模なアルゴリズムによる思考(「0-1-多数」および「範囲」と考える)を検討することをお勧めします。通常は論理*エラーです。 –

+4

あなたの特定の例では、継承はインターフェイスの再利用のための継承であり、実装の再利用ではないので、継承は非常に洗練されたソリューションではないと思います。 'operator []'は 'std :: vector'以外の例外をスローするので、インタフェースを再利用することはできません。コードを再利用するには、単純な共有関数を使用するか(この場合)、 'std :: vector'を' SomewhatSafeVector'のメンバにしてください。 –

+0

@KerrekSB:最初に、どうしてですか?第二に、私はそのようなトラブルを持っていません。しかし、私は境界をチェックコンテナは、教育やデバッグの目的のための良い考えだと思う。 –

答えて

6

私はいつもあなたが仮想デストラクタなしクラスから

を継承してはならない説明すべての複雑さがあまりにも多くの時間がかかり、それがあるので、これは初心者に与えられた経験則であることを聞きました(エクササイズプログラムにとってはそれほどコストがかかりません)、実際には(過度のこともありますが)すべての時間で機能するベースラインを実際に与えるだけです。

基本クラスのデストラクタvirtualを使用せずに完全に継承を使用できます。一方、基本クラスにvirtualメソッドがまったくない場合、継承はおそらくジョブの間違ったツールになります。 例:SafeVector<T> sv; sv[3];をご利用の場合はをご利用の場合は安全ですが、std::vector<T>& v = sv; v[3];はそうではありません。これは、を隠しているため、は基本クラスの方法で、上書きしませんレベル、彼らはあなたに知らせるでしょう)。

ここで正しい方法は、compositionを使用し、実際に使用するメソッドの実装メンバーに転送方法を作成することです。実際には、C++は委譲(using attribute.insert;)をサポートしていないので、疲れてしまいます。

また、自由なメソッドを自由なメソッドとして追加することもできます。 「OO」という考え方を持つ人々にとっては慣用的ではないかもしれませんが、一部の演算子を追加することはできません。

5

あなたはクラスのポリモーフィック(派生オブジェクトへの無削除ベースポインタ)を使用する予定がない場合、それは未定義の動作ではありません。

リファレンス:

C++ 03標準:5.3.5

5.3.5/1を削除:

削除発現オペレータが最も派生オブジェクトを破棄(1.8)または新しい式で作成された配列。
削除-の式:
::キャスト式に削除選ぶ
::選ぶ削除[]キャスト式

5.3.5/3:最初に

オペランドの静的型がその動的型と異なる場合、静的型はオペランドの動的型の基本クラスでなければならず、静的型は仮想型デストラクタを持つか、動作は未定義です。あなたは多形、そのオブジェクトを使用することを歓迎している第二の代替(アレイを削除)でオブジェクトの動的な型はその静的な型と異なっを削除する場合は、動作がundefined.73ある)

4

、あなただけのことができます'deleteそれは多形的にそれです。クラスのオブジェクトへのポインタをstd::vector<>*経由で削除しないようにすると、安全です。別に

:あなたはあなたのoperator[]ので、簡素化かもしれません:あなたは(つまり、決してアップキャスト参照またはポインタである)多型を使用しない場合は

T& operator[](unsigned n) { return this->at(n); } 
2

はい、危険な破壊を実行する方法はありません。

Mixinクラスはこのようにしばしば使用され、カップルパターンの名前を付けるためにCRTPは仮想デストラクタを使用することはめったにありません。