基本クラスを宣言するときに、その中のすべての関数を仮想として宣言すべきですか、または仮想関数のセットと、継承されないと思われる非仮想関数のセットが必要ですか?すべての関数を基本クラスに仮想宣言する必要がありますか?
答えて
関数は、派生クラスがその関数を別の方法で実装する場合にのみ仮想関数である必要があります。例えば
:
class Base {
public:
void setI (int i) // No need for it to be virtual
{
m_i = i;
}
virtual ~Base() {} // Almost always a good idea
virtual bool isDerived1() // Is overridden - so make it virtual
{
return false;
}
private:
int m_i;
};
class Derived1 : public Base {
public:
virtual ~Derived() {}
virtual bool isDerived1() // Is overridden - so make it virtual
{
return true;
}
};
結果として、あなたはそれを上書きするつもりか、あなたが行動を必要とすることを発見するまで、ことを事前に知っている限り、私は、仮想何も持っていないの側面をエラーです。唯一の例外はデストラクタです。はほぼです。これは、基本クラスで常に仮想的にしたい場合です。
インターフェイス関数は、一般的に仮想である必要があります。固定機能を提供する関数は、そうしてはいけません。
私は仮想化したいものだけを作る傾向があります。上書きしたいものについての私の最初の仮定が間違っていると判明した場合、私は元のクラスに戻って変更します。
ああ、継承されるものに取り組んでいるなら、明らかに常にデストラクタを仮想にしてください。
実際に上書きするまで何かを宣言するのはなぜですか?私は、それが確実かどうかの問題ではないと信じています。事実に従う:それはどこかでオーバーライドされていますか?いいえ?それからそれは仮想であってはならない。
これは、1つのサブクラス(オーバーライドされていないメソッドをオーバーライドする)を変更する場合、メソッドを仮想にするためにベースクラスを変更する必要があるため、参照するすべてのコードを再コンパイルする必要がある基本クラスいくつかのプロジェクトでは、基本クラスの脆弱性は問題ではありませんが、他のプロジェクトではそれが問題になります。これは、ビルドプロセスと、基本クラスのインターフェイスを公開したかどうかによって異なります。 –
したがって、IMOメソッドは、サブクラスがそれらをオーバーライドすることが許可されていれば(そして実行時の多形性がサポートされていれば)、仮想でなければなりません。 –
あなたは、あなたが物事を次の操作を行うことができます(あなたは、誰かがクラスを派生していることを確認している)基本クラスを作成する場合:
- メイクデストラクタ仮想(基底クラスのための絶対必要)
- はどのメソッドを定義します を派生させて仮想化する必要があります。
- 非仮想とする必要がない(または、 はありません)方法を定義してください。
- 関数が派生した クラスのみで、基底クラスでない場合は、 を保護対象としてマークします。
基本型のポインタが仮想関数を呼び出すときに、どの実際のコードが実行されるかはコンパイラが分かりません。実行されるコードの実際の部分は、実行時にベースクラスポインタによってどのオブジェクトがポイントされるかによって評価される必要があります。したがって、関数が継承されたクラスでオーバーライドされない場合は、仮想関数の使用を避けてください。
TLDRバージョン: "仮想関数のセットと、継承されないと思われる非仮想関数のセットが必要です。"仮想関数は実行時にパフォーマンスが低下するためです。
仮想関数を上書きすることを意図し、設計するようにしてください。メソッドの仮想化はメンテナンスとパフォーマンス(メンテナンスがIMHOよりはるかに大きな問題になります)の面では無料ではありません。
メソッドが仮想になると、このメソッドを使用するコードについては推論するのが難しくなります。あるメソッド呼び出しが何をするかを考えるのではなく、そのシナリオでNメソッド呼び出しが何をするかを考慮する必要があります。 Nは、そのメソッドをオーバーライドするサブクラスの数を表します。
このルールの例外の1つはデストラクタです。彼らは派生することを意図されているどのクラスでも仮想でなければなりません。割り当て解除中に適切なデストラクタが呼び出されることを保証する唯一の方法です。
非仮想インターフェイスイディオム(C++コーディング標準規格39)では、基本クラスには非仮想インターフェイスメソッドが必要であり、基本クラスで不変条件が保証され、基本クラスのカスタマイズには非公開の仮想メソッド派生クラスによる振る舞い。非仮想インタフェースメソッドは、オーバーライド可能な動作を提供するために仮想メソッドを呼び出します。
ここにソースを追加することを検討してください。 「C++コーディング標準、101のルール、ガイドライン、ベストプラクティス、Herb SutterとAndrej Alexandrescu」を参照してください。ただし、C++には公式のコーディング標準はありません。 – patrik
少なくとも1つのメソッドがクラス内で仮想であるときは、仮想デストラクタを持つ必要があります。 – stefanB