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引用或指针的方式强制转换,按照父类内存结构重新解释,可改变成员的访问权限。
测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }