20

派生クラスが仮想関数をプライベートとして宣言するとどうなるかを理解しようとしていました。以下は私が書いたプログラムです

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void func() {
        cout<<"A::func called"<<endl;
    }
    private:
};
class B:public A
{
    public:
    B()
    {
        cout<<"B constructor called"<<endl;
    }
    private:
    void func() {
        cout<<"B::func called"<<endl;
    }
};
int main()
{
    A *a = new B();
    a->func();
    return 0;
}

驚いたことに(私にとって)出力は次のとおりです。

B constructor called
B::func called

これは、その機能のプライベート アクセス セットに違反していませんか。これは予想される動作ですか?これは標準的な回避策ですか、それとも抜け穴ですか? VTABLE を介して関数呼び出しを解決するときに、アクセス レベルはバイパスされますか?

この動作に関する洞察は非常に役立ちます。

さらに、仮想メンバーを非公開でオーバーライドすると、それ以上のクラスがそれを継承できなくなることが言及されました。これでも問題があります。上記のプログラムを次のように変更します。

class C: public B
{
    public:
    void func() {
        cout<<"C::func called"<<endl;
    }
};

そしてメインのテストプログラムは次のことを行います:

int main()
{
    A *a = new C();
    a->func();
    return 0;
}

出力は次のとおりです。

C::func called
4

3 に答える 3

13

これは明確に定義された動作です。これaB*コンパイルされない場合。その理由は、メンバー アクセスが実行時に動的に解決されるのではなく、コンパイラによって静的に解決されるためです。多くの C++ の本では、経験の浅いコーダーを混乱させるため、このようなコーディングは避けるように勧めています。

于 2009-06-30T04:31:35.053 に答える
3

さて、あなたはA::func()which を呼び出していますpublicが、Bオブジェクトでは によってオーバーライドされていB::func()ます。これは、次の意味を持つ一般的なパターンです。

  • func派生Bオブジェクトで呼び出されることを意図していません

  • funcから派生したクラスではオーバーライドできませんB

于 2009-06-30T04:36:22.043 に答える