C++の虚関数のアクセス制御とコンパイラのバインドポリシー


[updated]注意:ベースクラスのポインタは派生クラスが自分で定義した関数を呼び出すことができず、虚関数のみを呼び出すことができます!!!関数のバインドは静的であるため,実際に呼び出された関数こそ動的である.
次のコードに従います.
ここの文章のテーマは自作で、自分が虚関数のアクセス制御を発見しただけで、自分の前の理解と出入りがあるので、忘れてしまいました.
まず、虚関数は多態を実現するメカニズムであり、すなわち、ベースクラスのポインタまたは参照を用いて虚関数を呼び出す場合、そのポインタまたは参照の動的タイプに対応する関数が呼び出され、ここではいくつかの点を忘れなければならない.
1コンパイラは、呼び出し関数を決定する際に、その関数が虚関数である場合に実行時にどの関数を呼び出すかを決定し、虚関数でない場合、コンパイル段階で呼び出しの関数タイプ、例えば以下のコードを決定した.
ベースクラスと派生クラスは、関数fを宣言する.しかしmain関数の呼び出しではコンパイラが静的タイプに対応する関数を呼び出した.f関数は虚関数ではないため、ベースクラスと派生クラスでは宣言されているが.
これは明らかで,虚関数がなければ多態はなく,動的タイプも関係ない.関数のすべての呼び出しは静的バインドです.
2ベースクラス定義虚関数はpublicであり、派生クラスは虚関数を上書きするがprivateと宣言し、ベースクラスのポインタが派生クラスのオブジェクトにバインドされたときに、そのベースクラスポインタを使用して虚関数を呼び出すと、呼び出しが成功するかどうか.両者のアクセス権限が逆だったらね.
class Base
{
public:
    virtual void f(int i=0) {cout << "f() in Base..." << i << endl;}
};
class Derived:public Base
{
private:
    void f(int i=1){cout << "f() in derived..." << i << endl;}
};

int main(void)
{
    Base *b = new Derived();
    b->f();
    return 0;
}

上記コードの出力は、f()in derived 0
まず、出力結果がf()in derivedである理由を分析する.コンパイラは、bがfを呼び出すのを見たとき、bの静的タイプ(すなわちBase)に基づいてf関数がアクセス可能かどうかを決定する.f関数式publicのため、OK、「アクセス制御public」は呼び出しに影響を及ぼさず、パラメータのデフォルトパラメータの付与を行う.
fは虚関数であるため、どの関数を呼び出すかが実行時に決定されるので、実行時にDerivedの虚関数テーブルを検索して虚関数f(このときのfはすでにDerivedクラスで上書きされており、呼び出されたのが派生クラスのバージョンである.)を得る.
では、なぜiの値が0なのかについては、上記の分析でも説明していますが、文章を参照してクリックしてリンクを開くこともできます.
両方のアクセス権を交換すると、アクセス制御という関門は通れませんが、派生クラスがf関数を継承する必要がある以上、Baseクラスでprivateと宣言すること自体は間違っています.