6

重複の可能性:
C++: public\private 継承のオーバーライド

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

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

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

今、私が次のことをすると:

base *b = new child;
b->doSomething();    // Calls the derived class function even though that is private

質問:

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

継承アクセス指定子を public から protected/private に変更すると、コンパイル エラーが発生します。

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

注: 継承アクセス指定子の概念は認識しています。したがって、2 番目のケースでは、プライベート/保護されているため、アクセスできません。しかし、最初の質問への答えが気になります。どんな入力でも大歓迎です。

4

3 に答える 3

6

アクセス制御は実行時ではなくコンパイル時に実装されますが、ポリモーフィズム (仮想関数の使用を含む) は実行時の機能です。

于 2012-11-29T04:54:59.753 に答える
6

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

C++03 11.6「仮想関数へのアクセス」は次のように述べています。

仮想関数のアクセス規則 (第 11 節) は、その宣言によって決定され、後でそれをオーバーライドする関数の規則の影響を受けません。[例:

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
}

—終わりの例]

アクセスは、メンバー関数が呼び出されるオブジェクトを示すために使用される式の型 (上記の例では B*) を使用して、呼び出しポイントでチェックされます。メンバー関数が定義されたクラス (上記の例では D) でのメンバー関数のアクセスは、一般に不明です。

特に、「定義されたクラス (上の例では D) 内のメンバー関数へのアクセスは、一般に不明である」ことに注意してください。一般に、あなたの例の が呼び出された時点で、コンパイラは(または)b->doSomething();についてまったく知識がない可能性があり、アクセスがプライベートであるかどうかははるかに少ないです。derivedchildderived::doSomething()

于 2012-11-29T04:57:13.777 に答える
0

プライベート関数は、外部および派生クラスから非表示にすることを目的としています。親のDoSomethingのアクセス指定子をオーバーライドしてプライベートにしますが、基本クラスをインスタンス化しています。したがって、最初のケースでは、ベースのDoSomethingをパブリックとして呼び出すことができます。このシナリオは、派生クラスから派生する人々を停止したい場合に使用できます。

2番目のケースでは、privateアクセス指定子により、ベースのメンバーが派生クラスのユーザーに公開されなくなり、派生クラスが事実上役に立たなくなります。

于 2012-11-29T05:12:05.170 に答える