访问控制与继承

来源:互联网 发布:淘宝网企业店铺标志 编辑:程序博客网 时间:2024/05/18 17:01

protected成员:

1)和私有成员类似,受保护的成员对类的用户(实例)来说是不可访问的。

2)和公有成员类似,受保护的成员对于派生类的成员和友元来说是可访问的。

3)派生类的成员或友元只能通过派生类对象来访问基类的受保护成员(通过基类对象不能访问基类受保护成员)。

      派生类对于一个基类对象中的受保护成员没有任何访问特权。

class Base{protected:int prot_mem;};class Derived:public Base{friend void clobber(Derived&);   //能访问Sneaky::prot_memfriend void clobber(Base&);      //不能访问Base::prot_memint j;};void clobber(Derived &s){s.j = s.prot_mem = 0;            //正确}void clobber(Base &b){b.prot_mem = 0;                 //错误}
试想如果派生类能访问基类对象的受保护成员,那么我们可以建立一个类似的继承类,就可以通过基类对象来改变基类受保护的成员了,这与protected的目的(不让该类的用户访问)不符了。



派生说明符的目的:派生访问说明符(即以何种方式继承)对于派生类的成员(及友元)能否访问其直接基类的成员没什么影响,对基类成员的访问权限只与基类中的访问说明符有关。其目的是控制派生类用户(实例)对于基类成员的访问权限。

#include<iostream>  #include <string>#include <vector>using namespace std;class Base{public:void pub_mem();protected:int prot_mem;private:char priv_mem;};struct PubDerv :public Base{int f(){ return prot_mem; }    //正确,派生类能访问protected成员char g(){ return priv_mem; }   //错误,派生类不能访问private成员};struct PrivDerv:private Base{int f1() const{ return prot_mem; }  //正确,private继承不影响派生类对基类的访问权限};int main(){PubDerv d1;PrivDerv d2;d1.pub_mem();           //正确,pub_mem在派生类中是public的d2.pub_mem();           //错误,pub_mem在派生类中是private的return 0;}
同理,如果我们采用protected继承,则基类中所有公有成员在新定义的类中都是受保护的。


派生类向基类转换的可访问性:
1)只有当D公有继承B时,用户代码才能使用派生类向基类的转换;如果D继承B的方式是protected或private的,则用户代码不能使用该转换。

#include<iostream>    #include <string>  #include <vector>  using namespace std;class Base{public:void test(){ cout << "base test" << endl; }};class Derived :public Base{public:void test(){ cout << "derived test" << endl; }};class ProDerived :protected Base{public:void test(){ cout << "protected derived test" << endl; }};class PrivDerived :private Base{public:void test(){ cout << "private derived test" << endl; }};int main(){Base *a = new Derived();a->test();Base *b = new ProDerived();  //错误,不能转换Base *c = new PrivDerived();  //错误,不能转换return 0;}

2)无论D以什么方式继承B,D的成员函数和友元函数都能使用派生类向基类的转换。

#include<iostream>    #include <string>  #include <vector>  using namespace std;class Base{public:virtual void test(){ cout << "base test" << endl; }};class Derived :public Base{public:void test(){ cout << "derived test" << endl; }};class ProDerived :protected Base{public:void test(){ cout << "protected derived test" << endl; }void visitBase(){Base* b1 = new ProDerived();  //OKb1->test();}};class PrivDerived :private Base{public:void test(){ cout << "private derived test" << endl; }void visitBase(){Base* b1 = new PrivDerived();  //OKb1->test();}};int main(){ProDerived pro;pro.visitBase();PrivDerived priv;priv.visitBase();return 0;}//输出://protected derived test//private derived test
3)如果D继承B的方式是公有的或者受保护的,则D的派生类的成员和友元可以使用D向B的类型转换。如果继承方式是私有的,则不能使用。


友元与继承:
友元关系不能被继承,基类的友元在访问派生类成员时不具有特殊性,类似的,派生类的友元不能随意访问基类的成员。

class Base{friend class Pa1;protected:int prot_mem;};class Derived :public Base{friend void clobber(Derived&);   //能访问Sneaky::prot_mem  friend void clobber(Base&);      //不能访问Base::prot_mem  int j;};class Pa1{public:int f(Base b){ return b.prot_mem; }  //正确,Pa1是Base的友元int f2(Derived d){ return d.j; }     //错误,Pa1不是Derived的友元int f3(Derived d){ return d.prot_mem; }  //正确,Pa1是Base的友元(注意)};
对于f3可以访问,原因是Pa1可以访问基类的成员,这种可访问性包括了基类对象内嵌在其派生类对象中的情形。


改变个别成员的可访问性:

有时,我们需要改变派生类继承的某个名字的访问级别,通过使用using声明可以达到这一目的:

class Base{public:int size() const{ return n; }protected:int n;};class Derived :private Base{public:using Base::size;protected:using Base::n;};
派生类只能为那些它可以访问的名字提供using声明。


默认继承保护级别:
struct默认是公有继承,class默认是private继承。

0 0
原创粉丝点击