C++のベースクラスのプライベートメンバーは継承されますか?

4482 ワード

1.派生クラス間接アクセスベースクラスプライベートメンバー
クラスの継承では、クラスのプライベートメンバーは、派生クラスで「非表示」であり、この「非表示」とは、派生クラスのメンバー関数または派生クラスのオブジェクト(ポインタ、参照)を介して直接アクセスできません.ただし、直接アクセスできないのはアクセスできないという意味ではありません.派生クラスでは、プライベートメンバー変数およびプライベートメンバー関数を含む、ベースクラスの共有関数を呼び出すことによって、ベースクラスのプライベートメンバーに間接的にアクセスできます.以下の手順を考察する.
#include <iostream>
using namespace std;

class A{
    int i;
    void privateFunc(){
        cout<<"this is a private function of base class"<<endl;
    }

public:
    A(){i=5;}
    int getI(){
        return i;
    }

    void usePrivateFunc(){
        privateFunc();
    }
};

class B:public A{
public:
    void printBaseI(){
        cout<<getI()<<endl;
    }
    void usePrivateFunction(){
        usePrivateFunc();
    }
};

int main(){
    B b;
    b.printBaseI();
    b.usePrivateFunction();
    getchar();
}

プログラム出力結果:
5
this is a private function of base class

クラスBでは、ベースクラスAのメンバー変数iとメンバー関数privateFunc()がプライベートであるため、クラスBのメンバー関数では直接アクセスできません.ただし、クラスAの共有メンバー関数getI()はプライベートメンバー変数iにアクセスでき、usePrivateFunction()はプライベートメンバー関数privateFunc()にアクセスできるため、クラスBでは関数getI()とusePrivateFunc()を呼び出すことでベースクラスAのプライベートメンバーに簡単にアクセスできます.
2.プライベートメンバーは継承されますか
ベースクラスにプライベートメンバーへのアクセスの公有関数が提供されていない場合、そのプライベートメンバーは「存在する」のでしょうか.継承されるのではないでしょうか.実は、これらのプライベートメンバーは確かに存在し、継承されますが、プログラマーは通常のルートでアクセスできません.以下のプログラムを考察し、クラスのプライベートメンバーに特別な方法でアクセスしました.
#include <iostream>
using namespace std;

class A{
    int i;
    void privateFunc(){
        cout<<"this is a private function of base class"<<endl;
    }

public:
    A(){i=5;}
};

class B:public A{
public:
    void printBaseI(){
        int* p=reinterpret_cast<int*>(this);//          
        cout<<*p<<endl;
    }

    void usePrivateFunction(){
        void (*func)()=NULL;
        _asm{
            mov eax,A::privateFunc;
            mov func,eax;
        }
        func();
    }
};

int main(){
    B b;
    b.printBaseI();
    b.usePrivateFunction();
}

プログラム出力結果:
5
this is a private function of base class

(1)クラスAは、プライベートメンバー変数iにアクセスするための公有的な方法を提供していないが、クラスA(およびクラスAの派生クラス)オブジェクトのうちの1つには、変数iが含まれる.
(2)クラスAはプライベートメンバ関数privateFunc()にアクセスする公有関数を提供していないが,プログラムコード領域には関数privateFunc()のコードが依然として存在し,その関数のエントリアドレスをインラインアセンブリで取得することでスムーズに呼び出すことができる.
以上のように,クラスのプライベートメンバーは必ず存在し,派生クラスにも継承され,派生クラスにはベースクラスのプライベートメンバーが含まれていることも大きさから分かるように,読者は自分で考証することができる.ただし、C++構文の制限を受けると、派生クラスでベースクラスにアクセスするプライベートメンバーは間接的にしかできません.