[解決済み] プライベートな純粋仮想関数のポイントは何ですか?
質問
ヘッダーファイルで次のようなコードを見かけました。
class Engine
{
public:
void SetState( int var, bool val );
{ SetStateBool( int var, bool val ); }
void SetState( int var, int val );
{ SetStateInt( int var, int val ); }
private:
virtual void SetStateBool(int var, bool val ) = 0;
virtual void SetStateInt(int var, int val ) = 0;
};
私には、このことは
Engine
クラスまたはその派生クラスは、これらの純粋仮想関数の実装を提供する必要があります。しかし、派生クラスがこれらのプライベート関数を再実装するためにアクセスできるとは思えないのですが、なぜ仮想関数にするのでしょうか?
どうすればいい?
このトピックの質問は、かなり一般的な混乱を示唆しています。その混乱は十分に一般的であり C++のFAQ というのも、混乱は悪いことのように思われるからです。
はい、プライベート仮想関数は派生クラスでオーバーライドできます。派生クラスのメソッドは、基底クラスの仮想関数を呼び出すことはできませんが、その実装を独自に用意することは可能です。Herb Sutterによると、ベースクラスで非仮想的なパブリックインターフェースを持ち、派生クラスでカスタマイズ可能なプライベートな実装を持つことで、インターフェースの仕様と実装のカスタマイズ可能な動作の仕様の分離をより良くすることができる"だそうです。詳しくは、彼の記事 バーチャリティ" .
しかし、あなたが提示したコードにはもう一つ興味深い点があり、それはもう少し注意を払うべきだと私は思います。パブリックインターフェースはオーバーロードされた非仮想関数のセットで構成され、それらの関数は非パブリック、非オーバーロードの仮想関数を呼び出します。C++の世界の常として、これはイディオムであり、名前がついていて、もちろん便利なものです。その名は(驚きの、驚きの!)。
Public Overloaded Non-Virtuals Call Protected Non-Overloaded Virtuals"
に役立ちます。 隠蔽ルールを適切に管理する . 詳しくはこちら こちら ということですが、簡単に説明します。
の仮想関数があるとします。
Engine
クラスはそのインターフェイスでもあり、純粋仮想ではないオーバーロードされた関数の集合です。もしそれらが pure virtual であったとしても、以下のように、クラス階層の下位で、同じ問題に遭遇する可能性があります。
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);
の非表示を防がなかった場合は、「1.
Engine
のメンバーであれば、この文は
myV8->SetState(5, true);
を呼び出します。
void SetState( int var, int val )
を派生クラスから変換して
true
から
int
.
この例のように、インターフェイスが仮想ではなく、仮想実装が非公開であれば、派生クラスの作者は考えるべき問題がひとつ減り、単に
class MyTurbochargedV8 : public Engine
{
private:
void SetStateInt(int var, int val ) {/*new implementation*/}
};
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】'cout'は型名ではない
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】なぜ、サイズ8の初期化されていない値を使用するのでしょうか?
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー