2012-11-29 25 views
6

Possible Duplicate:
C++: overriding public\private inheritanceプライベート仮想関数

class base { 
public: 
    virtual void doSomething() = 0; 
}; 

class derived : public base { 
private: // <-- Note this is private 

    virtual void doSomething() 
    { cout << "Derived fn" << endl; } 
}; 

は今

  1. をそれも、それかかわらず、派生クラスの関数を呼び出すことができますプライベートです。これはどのように可能ですか?

    'type cast' : conversion from 'Derived *' to 'base *' exists, but is inaccessible 
    

    注:私は、パブリックからプライベート/保護への継承アクセス指定子を変更した場合

は今、私はコンパイルエラーを取得する私は、継承アクセス指定子の概念を認識しています。だから、それがプライベート/保護された2番目のケースでは、アクセスできない。しかし、最初の質問に対する答えが不思議です。どんな入力も高く評価されます。

答えて

6

アクセス制御は実行時ではなくコンパイル時に実装され、多態性(仮想関数の使用を含む)は実行時機能です。

+0

私は、エラーの原因を知るのではなく、アクセス指定がそのように機能する理由を知りたいと思うと思います。 – Hossein

6

最初のケースでは、呼び出しが行われた静的型のアクセスチェックが(常に行われるので)実行されます。 *bの静的タイプはbaseであり、その場合doSomething()publicです。

C++ 03 11.6「仮想関数へのアクセスは、」言う:

The access rules (clause 11) for a virtual function are determined by its declaration and are not affected by the rules for a function that later overrides it. [Example:

class B { 
public: 
    virtual int f(); 
}; 

class D : public B { 
private: 
    int f(); 
}; 

void f() 
{ 
    D d; 
    B* pb = &d; 
    D* pd = &d; 

    pb->f(); //OK:B::f()is public, 
      // D::f() is invoked 
    pd->f(); //error:D::f()is private 
} 

—end example]

Access is checked at the call point using the type of the expression used to denote the object for which the member function is called (B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.

は特に「と心の中で、上記の例では、それが定義されたクラスのメンバ関数のアクセス(Dをキープ)は一般的に知られていません "。一般に、b->doSomething();が呼び出された時点では、コンパイラは(またはchild)について全く知らないかもしれません。derived::doSomething()へのアクセスがプライベートであるかどうかははるかに低くなります。

0

プライベート関数は、外界や派生クラスから隠されることを意図しています。親のDoSomethingのアクセス指定子をオーバーライドしてプライベートにしていますが、基本クラスをインスタンス化しています。したがって、最初のケースでは、それが公開されているようにBaseのDoSomethingを呼び出すことができます。このシナリオは、派生クラスから派生した人々を停止させたい場合に使用できます。

2番目のケースでは、アクセス指定子privateは、派生クラスのユーザーに公開されないベースのメンバーを作成します。これにより、派生クラスは実質的に役に立たなくなります。

+0

OPはかなり明確です** **派生クラス関数**を呼び出すことができます。あなたの推測**については、それが公開されているようにベースのDoSomethingを呼び出すことができます**与えられた例に基づいて間違っており、質問1の答えではありません。 – StahlRat