1

Herb Sutter の有名な記事Virtualityは、次のように述べています。

ガイドライン #2: 仮想関数を private にすることを好みます。

簡単だ。これにより、派生クラスは関数をオーバーライドして、必要に応じて動作をカスタマイズできます。派生クラスによって仮想関数を呼び出し可能にすることで、仮想関数を直接公開する必要はありません (関数が単に保護されている場合に可能になります)。

以下のコードでは、private_base_func() は基本クラスで宣言されたプライベート仮想関数であり、被駆動クラス コンストラクターで呼び出されます。奇妙なことに、このコードは正常にコンパイルされ、被駆動クラスから基本クラスのプライベート仮想関数を呼び出します。上の発言と矛盾します。これは私を非常に混乱させています。

class base
{
public:

    base() {}
    virtual ~base(){}

private:
    virtual void private_base_func() 
    { 
        std::cout << "Base Class invoke" << std::endl;
    }

};


class drived : public base
{
public:
    drived()
    {
        private_base_func(); // this line should not compile
    }

private:
    // Overriding base class virtual function
    void private_base_func() 
    { 
        std::cout << "Drived class invoke" << std::endl;
    }
};

int main()
{
   base* ptr = new drived();
   return 0;
}

返信ありがとうございます

4

2 に答える 2

8

これは、もちろん 内でアクセス可能なdrivedのバージョンの を呼び出しているためです。呼び出すことができない関数はのバージョンです:private_base_funcdrivedbase

drived()
{
    base::private_base_func(); // this line will not compile
}
于 2013-04-03T21:03:49.280 に答える
1
    private_base_func(); // this line should not compile

どうして?private_base_funcprivate関数でdrivedあり、その行は 内drivedにあるため、それを呼び出してもまったく問題ありません。これは次のものとは異なることに注意してください。

drived()
{
    base b;
    b.private_base_func(); // this line does not compile
}

いずれにせよ、それは記事の目的ではありません。この記事の要点は、基本クラスで 2 つの異なるインターフェイスが定義されていることです。1 つは公開インターフェースで、ベースのユーザーが必要とする操作を提供します。もう 1 つは仮想関数のセットで、拡張機能が基本クラスに提供する操作を定義します。両方のインターフェイスを分離することで、ユーザーをプロバイダーから切り離し、柔軟性を得ることができます。

于 2013-04-03T21:04:37.257 に答える