2016-12-14 2 views
2
using namespace std; 
#include <cstdio> 
#include <iostream> 

class One{ 
    private: 
     virtual void func(){ 
      cout<<"bark!"<<endl; 
     } 
}; 

class Two: public One{ 
    public: 
     void func(){ 
      cout<<"two!"<<endl; 
     } 
}; 

int main(){ 
    One *o = new Two(); 
    o->func(); 
} 

なぜo->func()にエラーがありますか?プライベート仮想関数が派生クラスのパブリック関数としてオーバーライドされている場合、どのような問題がありますか?

私は私の意見では、o->func()は公開され、派生クラスでfunc()を呼び出す必要がありますので、問題はないだろう...その背後にあるメカニズムを知りませんが、それは言う:

error: ‘virtual void One::func()’ is private 
+7

貧しい奪わクラスを参照してください:?。? '( – qxz

答えて

11

アクセシビリティチェックは、オブジェクトの静的タイプに基づいて実行されます。 oのタイプはOne*です。つまり、One::func()privateの場合、o->func()はコンパイルされません。

一方、どの仮想メンバ関数が呼び出される(つまり動的ディスパッチ)かは、オブジェクトの動的型に基づいて実行時に発生します。したがってOne::func()publicの場合、oTwoのオブジェクトを指しているので、o->func()Two::func()を呼び出します。

サンプルコードと使用例については、One::func()privateとすることは意味がありません。しかし、Non-Virtual Interfaceと呼ばれる有名なイディオムがあり、これは基本クラスの仮想メンバ関数privateを使用しています。


その他の提案:

  1. delete o;
  2. に忘れてはいけませんが、基本クラスOneで仮想デストラクタを追加します。そうでなければdelete o;は未定義の動作につながります。例えばTwoのデストラクタが呼び出されないことがあります。

    class One { 
        public: 
         virtual ~One() {} 
        // ... 
    }; 
    
+0

をfuncは()基底クラスで純粋仮想関数が何であるかどうかは問題ではありません – lily

+1

なぜ、それを希望可視性が同じで、純粋仮想はただ何があります意味しません – Donnie

+0

@lily 'func()'が 'private'の場合は何も変わりません – songyuanyao

1

サブクラスが継承制限を緩和することはできません、funcが仮想である にもかかわらず、それはまだ制約が残る継承です。

継承制限のcompliatedビューのこの答えを参照してください。

Difference between private, public, and protected inheritance

+1

C++のサブクラスは、それ自体がアクセスできる継承されたメンバ(データまたは関数)のアクセシビリティ(またはあなたの命名規則に従うための "継承制限")を実際に変更することができます。/6vn729)などです。 – StoryTeller

1

Access specifiers and virtual functionsを確認してください。規格から

§11.5仮想 関数のアクセス規則(条項11)は、その宣言によって決定され、機能するため 規則によって影響されない[class.access.virt]後でそれを上書きします。

アクセスポイントは、メンバー関数が呼び出されたオブジェクトを表す式 の型を使用してチェックされます。 定義されたクラスのメンバ関数へのアクセスは、一般には知られていません。 です。

仮想関数の実行可能関数がnameルックアップによって決定された場合、仮想関数のアクセス指定子は、関数の名前を指定するオブジェクト式の静的型のスコープでチェックされます。実行時に、呼び出される実際の関数は、完全に異なるアクセス指定子を持つ派生クラスで定義できます。これは、「アクセス指定子」がコンパイル時の現象であるためです。

func()のアクセス指定子がOne *oの範囲でチェックされており、クラスOneでプライベートであるため、エラーが発生します。

Oneが公開の場合はfunc()と宣言し、Twoの場合はプライベートと宣言してもエラーは発生しません。このPrivate function invoked and it works. Could any of you reason it please

関連する問題