C++ 访问权限问题主要包括两种:一种是外界对类成员的普通访问,主要通过类内的public、protected、;另一种是继承关系中子类对父类成员的访问。

基本原则:外界只能访问类中public成员,子类可访问父类的public和protected成员;不同继承方式只影响外界(包括子类的子类)通过子类对父类成员的访问权限。

 

一、 外界对类成员的普通访问

1. 当类成员在类中为public权限时,才可在类外访问,其余不可。

2. 若存在继承关系,从父类继承来的成员若在该类中仍具有public权限,也可在类外访问,其余不可。

   
二、继承关系中子类对父类成员的访问

1. 无论通过什么方式(public、protected、private)继承,在子类内部均可访问父类中的public、protected成员,private成员不可访问。

    注意:

      继承方式只影响外界(包括子类的子类)通过子类对父类成员的访问权限。

      public继承,父类成员的访问权限全部保留至子类;

      protected继承,父类public成员的访问权限在子类中降至protected;

      private继承,父类public、protected成员的访问权限在子类中均降至private。

2. 父类的析构函数若声明为protected (无论有无virutal),外界均不可调用delete 父类指针;因为是protected权限,子类析构后会自动调用父类析构函数。

   这种情况下,最好不要在父类成员中有动态内存分配。

3. 通过protected/private继承的子类,不能通过static_cast/dynamic_cast向父类转换;只能通过reinterpret_cast引用或指针的方式强制转换,按照父类内存结构重新解释,可改变成员的访问权限。

 

测试代码:

  1 #include <stdio.h>
  2 using namespace std;
  3 class Base
  4 {
  5     public:
  6     Base(){printf("Base construct!\n");bpb=1;bpt=2;bpv=3;}
  7     int bpb;
  8     protected:
  9     ~Base(){printf("Base destructor!\n");}
 10     int bpt;
 11     private:
 12     int bpv;
 13 };
 14 //一层继承
 15 class Derived_PB: public Base
 16 {
 17     public:
 18     Derived_PB(){printf("Derived_PB construct!\n");}
 19     
 20     ~Derived_PB(){printf("Derived_PB destructor!\n");}
 21     void display()
 22     { 
 23         printf("Base Public value: bpb=%d\n",bpb);
 24         printf("Base Protected value: bpt=%d\n",bpt);
 25 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 26     }
 27 };
 28 class Derived_PT: protected Base
 29 {
 30     public:
 31     void display()
 32     { 
 33         printf("Base Public value: bpb=%d\n",bpb);
 34         printf("Base Protected value: bpt=%d\n",bpt);
 35 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 36     }
 37 };
 38 class Derived_PV: private Base
 39 {
 40     public:
 41     void display()
 42     { 
 43         printf("Base Public value: bpb=%d\n",bpb);
 44         printf("Base Protected value: bpt=%d\n",bpt);
 45 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 46     }
 47 };
 48 //二层继承
 49 class Derived_PBB: public Derived_PB
 50 {
 51     public:
 52     void display()
 53     { 
 54         printf("Base Public value: bpb=%d\n",bpb);
 55         printf("Base Protected value: bpt=%d\n",bpt);
 56 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 57     }
 58 };
 59 
 60 class Derived_PTB: public Derived_PT
 61 {
 62     public:
 63     void display()
 64     { 
 65         printf("Base Public value: bpb=%d\n",bpb);
 66         printf("Base Protected value: bpt=%d\n",bpt);
 67 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 68     }
 69 };
 70 class Derived_PVB: public Derived_PV
 71 {
 72     public:
 73     void display()
 74     { 
 75 //        printf("Base Public value: bpb=%d\n",bpb);//error: bpb not accessible because Derived_PV private inherited from Base,use Base::bpb is the same
 76 //        printf("Base Protected value: bpt=%d\n",bpt);//error: cannot access inaccessible member declared in Base
 77 //        printf("Base Private value: bpv=%d\n",bpv);//error: cannot access private member
 78     }
 79 };
 80 int main()
 81 {
 82 //************************** test Base destructor **************************//
 83     Base *b=new Derived_PB();
 84 //    delete b;//error:  cannont access protected member (protected ~Base()),no matter whether Base destructor is virtual or not
 85     delete static_cast<Derived_PB*>(b);
 86     /*Base construct!
 87     Derived_PB construct!
 88     Derived_PB destructor!
 89     Base destructor!
 90     */
 91     
 92     
 93 //************************** test 一层继承访问权限 **************************//
 94     Derived_PB    DPB;
 95     printf("Base Public value: bpb=%d\n",DPB.bpb);
 96 //    printf("Base Protected value: bpt=%d\n",DPB.bpt);//error: cannot access protected member
 97 //    printf("Base Private value: bpv=%d\n",DPB.bpv);//error: cannot access private member
 98     
 99     Derived_PT    DPT;
100 //    printf("Base Public value: bpb=%d\n",DPT.bpb);//error: bpb is not accessible because protected inherited
101 //    printf("Base Protected value: bpt=%d\n",DPT.bpt);//error: cannot access Base protected member
102 //    printf("Base Private value: bpv=%d\n",DPT.bpv);//error: cannot access Base private member
103     
104     Derived_PV    DPV;
105 //    printf("Base Public value: bpb=%d\n",DPV.bpb);//error: bpb is not accessible because private inherited
106 //    printf("Base Protected value: bpt=%d\n",DPV.bpt);//error: cannot access Base protected member
107 //    printf("Base Private value: bpv=%d\n",DPV.bpv);//error: cannot access Base private member
108     
109 //************************** test 两层继承访问权限 **************************//
110 
111     Derived_PBB    DPBB;
112     printf("Base Public value: bpb=%d\n",DPBB.bpb);
113 //    printf("Base Protected value: bpt=%d\n",DPBB.bpt);//error: cannot access protected member
114 //    printf("Base Private value: bpv=%d\n",DPBB.bpv);//error: cannot access private member
115     
116     Derived_PTB    DPTB;
117 //    printf("Base Public value: bpb=%d\n",DPTB.bpb);//error: bpb is not accessible because Derived_PT protected inherited from  Base
118 //    printf("Base Protected value: bpt=%d\n",DPTB.bpt);//error: cannot access Base protected member
119 //    printf("Base Private value: bpv=%d\n",DPTB.bpv);//error: cannot access Base private member
120     
121     Derived_PVB    DPVB;
122 //    printf("Base Public value: bpb=%d\n",DPVB.bpb);//error: bpb is not accessible because Derived_PV private inherited from Base
123 //    printf("Base Protected value: bpt=%d\n",DPVB.bpt);//error: cannot access Base protected member
124 //    printf("Base Private value: bpv=%d\n",DPVB.bpv);//error: cannot access Base private member
125 
126 //************************** test 强制转换改变访问权限 **************************//
127 //    Base *pb=new Derived_PVB();//error: conversion from Derived_PVB* to Base* exists,but is inaccessible,use static_cast<Base *> is the same
128 //    Base *pb=new Derived_PV();//error: conversion from Derived_PV* to Base* exists, but is inaccessible
129     Base *pb=new Derived_PBB();//right
130     printf("Base Public value: bpb=%d\n",pb->bpb);//Base Public value: bpb=1
131     
132     Base *pb1=reinterpret_cast<Base *>(new Derived_PVB());//error: conversion from Derived_PVB* to Base* exists, but is inaccessible
133     printf("Base Public value: bpb=%d\n",pb1->bpb);//Base Public value: bpb=1
134     
135     return 0;
136 }
View Code