トピックの質問は、かなり一般的な混乱を示唆しています。混乱は十分に一般的であり、混乱は悪いことのように思われたため、C++FAQは長い間プライベート仮想の使用に反対していました。
したがって、最初に混乱を取り除くために:はい、プライベート仮想関数は派生クラスでオーバーライドできます。派生クラスのメソッドは、基本クラスから仮想関数を呼び出すことはできませんが、独自の実装を提供することはできます。Herb Sutterによると、基本クラスにパブリック非仮想インターフェイスがあり、派生クラスでカスタマイズできるプライベート実装があると、「実装のカスタマイズ可能な動作の仕様からインターフェイスの仕様を分離」することができます。あなたは彼の記事「仮想性」でそれについてもっと読むことができます。
しかし、私の意見では、あなたが提示したコードにはもう1つ興味深いことがあります。それは、もう少し注意を払う価値があります。パブリックインターフェイスは、オーバーロードされた非仮想関数のセットで構成され、これらの関数は、非パブリック、非オーバーロードの仮想関数を呼び出します。C ++の世界ではいつものように、それはイディオムであり、名前があり、もちろん便利です。名前は(サプライズ、サプライズ!)
「パブリックオーバーロードされた非仮想は、保護された非オーバーロード仮想を呼び出します」
非表示ルールを適切に管理するのに役立ちます。詳細についてはこちらをご覧くださいが、すぐに説明します。
Engine
クラスの仮想関数がそのインターフェースでもあり、純粋仮想ではないオーバーロードされた関数のセットであると想像してください。それらが純粋な仮想である場合でも、以下で説明するように同じ問題が発生する可能性がありますが、クラス階層の下位にあります。
class Engine
{
public:
virtual void SetState( int var, bool val ) {/*some implementation*/}
virtual void SetState( int var, int val ) {/*some implementation*/}
};
ここで、派生クラスを作成し、引数として2つのintを受け取るメソッドに対してのみ新しい実装を提供する必要があると仮定します。
class MyTurbochargedV8 : public Engine
{
public:
// To prevent SetState( int var, bool val ) from the base class,
// from being hidden by the new implementation of the other overload (below),
// you have to put using declaration in the derived class
using Engine::SetState;
void SetState( int var, int val ) {/*new implementation*/}
};
派生クラスにusing宣言を入れるのを忘れた場合(または2番目のオーバーロードを再定義する場合)、以下のシナリオで問題が発生する可能性があります。
MyTurbochargedV8* myV8 = new MyTurbochargedV8();
myV8->SetState(5, true);
メンバーの非表示を防止しなかった場合はEngine
、次のステートメントを使用します。
myV8->SetState(5, true);
void SetState( int var, int val )
派生クラスから呼び出し、に変換true
しint
ます。
例のように、インターフェースが仮想ではなく、仮想実装が非公開である場合、派生クラスの作成者は、考える問題が1つ少なくなり、簡単に記述できます。
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};