なぜこれが起こるのですか?
http://coliru.stacked-crooked.com/a/e1376beff0c157a1
class Base{
private:
virtual void do_run() = 0;
public:
void run(){
do_run();
}
};
class A : public Base {
public:
// uplift ??
virtual void do_run() override {}
};
int main()
{
A a;
a.do_run();
}
[〜#〜] private [〜#〜]仮想メソッドをパブリックとしてオーバーライドできるのはなぜですか?
https://en.cppreference.com/w/cpp/language/virtual#In_detail によると、ベースのvirtual
メンバー関数をオーバーライドすると、関数名、パラメーター、const/volatile-nessおよびref修飾子。戻り値の型やアクセス修飾子など、気になると思われるものは気にしません。
リンクされたリファレンスは、特に次のようにも述べています。
Base :: vfをオーバーライドするために表示する必要はありません(プライベートとして宣言するか、プライベート継承を使用して継承できます)。
私が明示的に見つけることができるものはこれを行う許可を与えていませんが、オーバーライドのルールはそれを妨げません。 virtual
関数および既存の関数をオーバーライドする関数によって許可されており、このケースを禁止していません。
なぜこれが言語であるかを尋ねている場合、標準化委員会に尋ねる必要があるかもしれません。
その動作は意図されています。メソッドが仮想の場合、アクセス修飾子に関係なく、派生クラスでカスタマイズできることを意味します。
こちら を参照
プライベート仮想メソッドをパブリックとしてオーバーライドできるのはなぜですか?
あなたが間違った角度で基本メソッドがプライベートであることを見るからです。 _B::do_run
_プライベートであることは、「このクラスのメンバーと友達だけが使用できる」という意味です。派生クラスによるオーバーライドを禁止するには、個別の指定子が必要ですが、virtual
ではなく単純に指定できます。別の側のクラスA
を使用すると、誰でもA::do_run()
を呼び出すことができます。そうするかどうかは、クラスA
デザイナーが決定します。ですから、あなたが見るように隆起はありません。
この実装は、基本クラスへのアクセス方法と構成を変更しないことに注意してください。
Base& b = a;
b.do_run();
動作しないでしょう。
Scott Meyersによる「Effective C++」でより詳細に説明されているその背後にある理論的根拠があることを覚えています。ただし、重要な実用的な機能は、そのような柔軟性を反対方向に使用できること、パブリックベースクラスメンバーを派生クラスのプライベート関数でオーバーライドして、クライアントにインターフェイスとしてベースクラスを使用させ、直接使用するように誘惑しないことです。隠された実装のままであるはずの派生物。
目的が基本クラスのプライベートコードを記述し、それをオーバーライドする可能性を防ぐことである場合は、基本クラスにプライベート関数を実装し、final
と宣言します。それ以外の場合:誰かがプライベート仮想を使用する必要がある場合? ISOCPP.ORG FAQ