アクセス制御
アクセス指定子
前章では、クラスの継承の基本的な動作について説明しました
この章では、これまで曖昧になっていたアクセス制御の詳細と
クラスの継承時に指定するアクセス指定の詳細について、詳しく説明します
クラスのメンバのアクセス指定のうち、public を指定したメンバを公開メンバと呼び
逆に private を指定した(class はデフォルトで private)メンバを非公開メンバと呼びます
公開メンバはあらゆる場所からアクセスできますが、非公開メンバはそのクラス内からのみアクセス可能です
非公開メンバへクラスの外部や派生クラスからのアクセスはできません
クラスを継承する時に、前回は public を指定しました
この時に指定するアクセス制御は、基本クラスのメンバをどのように継承するかを決定します
ここに public を指定すると、基本クラスの公開メンバを
そのまま公開メンバとして継承するということです
#include<iostream>
using namespace std;
class Base {
public:
char *str;
} ;
class Derived : public Base {
public:
void printStr() { cout << str; }
} obj ;
int main() {
obj.str = "Kitty on your lap";
obj.printStr();
return 0;
}
Derived は Base クラスを public で継承しています
これによって、Base クラスの公開メンバは Derived クラスでも公開メンバとして扱われます
Derived クラスや、まったく関係のない main() 関数からアクセスしているのがわかりますね
非公開メンバへは、たとえ派生クラスからでもアクセスすることはできません
次のプログラムを実行すると、コンパイルエラーになります
#include<iostream>
using namespace std;
class Base {
char *str;
} ;
class Derived : public Base {
public:
void printStr() { cout << str; }
} obj ;
int main() {
obj.printStr();
return 0;
}
Base クラスの str メンバ変数はデフォルトの private すなわち非公開メンバです
これに派生クラス Derived のメンバ関数 printStr() からアクセスしているためエラーになります
継承時のアクセス指定を private にすることもできます
つまり、上のプログラムの継承を class Derived : private Base とします
こうすると、基本クラスのメンバは派生クラスの非公開メンバとして継承されます
private で継承した場合、基本クラスの公開メンバへのアクセスは派生クラスからは可能です
しかし、派生クラスのオブジェクトを用いて外部からアクセスすることはできません
#include<iostream>
using namespace std;
class Base {
public:
char *str;
} b_obj ;
class Derived : private Base {
public:
void setStr(char *str) { this->str = str; }
void printStr() { cout << str; }
} d_obj ;
int main() {
b_obj.str = "Card Captor Sakura\n"; //アクセス可能
cout << b_obj.str;
d_obj.setStr("Kitty on your lap\n"); //d_obj.str はアクセスできない
d_obj.printStr();
return 0;
}
Derived は private 指定子を用いて Base クラスを継承しています
この場合、Derived クラスでは Base クラスの公開メンバが非公開として継承されます
そのため、Derived クラス内でのアクセスは可能ですが、外部からBase クラスのメンバへはアクセスできません
ためしに、d_obj.steStr() ではなく、直接 main() 関数から d_obj.str でアクセスしてみてください
もちろんこれは、Base クラスのオブジェクトに影響することはありません
ところで、継承時のアクセス指定子は省略するとこができました
省略した場合は、private として継承されます
被保護
public と private の中間的なアクセス指定子が存在します
それが protected 指定子です
protected で指定されたメンバは被保護メンバと呼ばれます
派生クラスからもアクセスできる非公開メンバが被保護メンバといえます
被保護メンバへのアクセス権は、あくまで基本クラスかそのクラスの派生クラスのみが保有します
protected 指定子の構文は、他のアクセス指定子と同じです
#include<iostream>
using namespace std;
class Base {
protected:
char *str;
};
class Derived : public Base {
public:
void setStr(char *str) { this->str = str; }
void printStr() { cout << str; }
} obj ;
int main() {
obj.setStr("Kitty on your lap");
obj.printStr();
return 0;
}
Base クラスのオブジェクトから メンバ変数 str へのアクセス方法はありません
しかし、被保護メンバへのアクセスは派生クラスからならば可能です
Derived クラスは str へ値を代入する setStr() メンバ関数などをサポートしています
被保護メンバである str へは、Base 及びその派生クラスである Derived クラスからのみアクセスできます
protected はクラスの継承時のアクセス指定に用いることも可能です
protected で継承した場合、基本クラスの公開メンバ、被保護メンバが被保護メンバとして継承されます
基本クラスの機能をカプセル化し、派生クラスで実装している機能のみを提供する時に使えます
#include<iostream>
using namespace std;
class Base {
char *str;
public:
char * getStr() { return str; }
char ** getPo() { return &str; }
};
class Derived : protected Base {
public:
void setStr(char *str) {
char **po = getPo();
*po = str;
}
void printStr() { cout << getStr(); }
} obj ;
int main() {
obj.setStr("Kitty on your lap");
obj.printStr(); //cout << obj.getStr(); これはエラーになる
return 0;
}
Derived クラスは protected で Base クラスを継承しています
これによって、Baseクラスの公開、被保護メンバは被保護メンバとして継承されます
Baseクラスのオブジェクトならば、Baseクラスの公開メンバには直接アクセスできます
しかし、Derived クラスは Base クラスの公開メンバを被保護メンバとして継承しているため
Derived クラスのオブジェクトはこれに直接アクセスすることができません
private と違うのは Derived クラスを継承したクラスもこの被保護メンバへアクセスできる点です
多重継承については、このあとさらに詳しく説明します
public
1 . public: [member-list]
2 . public base-class
1の場合、クラスのメンバへのアクセス制御を指定します
これを指定した後のメンバは、公開メンバとしてあらゆる場所からのアクセスを可能とします
2の場合、クラスの継承時に指定するアクセス制御です
これを指定した派生クラスは、基本クラスの公開メンバをそのまま公開メンバとして継承します
member-list : メンバを定義します
base-class : 基本クラスを指定します
private
1 . private: [member-list]
2 . private base-class
1の場合、クラスのメンバへのアクセス制御を指定します
これを指定した後のメンバは、非公開メンバとして同一クラス内からのアクセスだけを許可します
2の場合、クラスの継承時に指定するアクセス制御です
これを指定した派生クラスは、基本クラスの公開メンバを非公開メンバとして継承します
member-list : メンバを定義します
base-class : 基本クラスを指定します
protected
1 . protected: [member-list]
2 . protected base-class
1の場合、クラスのメンバへのアクセス制御を指定します
これを指定した後のメンバは、被保護メンバとして同一クラス及び派生クラスからのアクセスを許可します
2の場合、クラスの継承時に指定するアクセス制御です
これを指定した派生クラスは、基本クラスの公開メンバ及び被保護メンバを被保護メンバとして継承します
member-list : メンバを定義します
base-class : 基本クラスを指定します