トピックの質問はかなり一般的な混乱を示唆しています。混乱はよくあることであり、混乱は悪いことのように思われたので、C ++ FAQは長い間、プライベートバーチャルの使用を推奨していませんでした。
したがって、まず混乱を取り除くために:はい、プライベート仮想関数を派生クラスでオーバーライドできます。派生クラスのメソッドは、基本クラスから仮想関数を呼び出すことはできませんが、独自の実装を提供できます。Herb Sutterによると、基本クラスにパブリック非仮想インターフェイスがあり、派生クラスでカスタマイズできるプライベート実装があると、「インターフェイスの仕様と実装のカスタマイズ可能な動作の仕様の分離」が改善されます。詳細については、彼の記事「Virtuality」を参照してください。
しかし、私の意見では、あなたが提示したコードにはもう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*/}
};