理解public,protected 以及 private
经常看到在类中看到public,protected,private以及它们在继承中表示的一些访问范围,很容易搞糊涂。我们首先要明白下面几点。
1.类的一个特征就是封装,public和private作用就是实现这一目的。所以:
用户代码(类外)可以访问public成员而不能访问private成员;private成员只能由类成员(类内)和友元访问。
2.类的另一个特征就是继承,protected的作用就是实现这一目的。所以:
protected成员可以被派生类对象访问,不能被用户代码(类外)访问。
1 #include<iostream> 2 #include<assert.h> 3 using namespace std; 4 5 class A{ 6 public: 7 8 int a; 9 10 A(){ 11 a1 = 1; 12 a2 = 2; 13 a3 = 3; 14 a = 4; 15 } 16 17 void fun(){ 18 cout << a << endl; //正确 19 cout << a1 << endl; //正确 20 cout << a2 << endl; //正确,类内访问 21 cout << a3 << endl; //正确,类内访问 22 } 23 24 public: 25 int a1; 26 protected: 27 int a2; 28 private: 29 int a3; 30 }; 31 32 int main(){ 33 34 35 A itema; 36 itema.a = 10; //正确 37 itema.a1 = 20; //正确 38 itema.a2 = 30; //错误,类外不能访问protected成员 39 itema.a3 = 40; //错误,类外不能访问private成员 40 41 system("pause"); 42 return 0; 43 }
/****************继承中的特点***********************/
先记住:不管是否继承,上面的规则永远适用!
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
1.public继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:public, protected, private
2.protected继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:protected, protected, private
3.private继承:基类public成员,protected成员,private成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
1.private成员只能被本类成员(类内)和友元访问,不能被派生类访问;
2.protected成员可以被派生类访问。
看以下代码:
1.public继承
1 #include<iostream> 2 #include<assert.h> 3 using namespace std; 4 5 class A{ 6 public: 7 8 int a; 9 10 A(){ 11 a1 = 1; 12 a2 = 2; 13 a3 = 3; 14 a = 4; 15 } 16 17 void fun(){ 18 cout << a << endl; //正确 19 cout << a1 << endl; //正确 20 cout << a2 << endl; //正确 21 cout << a3 << endl; //正确 22 } 23 24 public: 25 int a1; 26 protected: 27 int a2; 28 private: 29 int a3; 30 }; 31 32 class B : public A{ 33 public: 34 int a; 35 B(int i){ 36 A(); 37 a = i; 38 } 39 40 void fun(){ 41 cout << a << endl; //正确,public成员 42 cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。 43 cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。 44 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 45 } 46 }; 47 48 int main(){ 49 50 B b(10); 51 cout << b.a << endl; 52 cout << b.a1 << endl; //正确 53 cout << b.a2 << endl; //错误,类外不能访问protected成员 54 cout << b.a3 << endl; //错误,类外不能访问private成员 55 56 system("pause"); 57 return 0; 58 }
2.protected继承:
1 #include<iostream> 2 #include<assert.h> 3 using namespace std; 4 5 class A{ 6 public: 7 8 int a; 9 10 A(){ 11 a1 = 1; 12 a2 = 2; 13 a3 = 3; 14 a = 4; 15 } 16 17 void fun(){ 18 cout << a << endl; //正确 19 cout << a1 << endl; //正确 20 cout << a2 << endl; //正确 21 cout << a3 << endl; //正确 22 } 23 24 public: 25 int a1; 26 protected: 27 int a2; 28 private: 29 int a3; 30 }; 31 32 class B : protected A{ 33 public: 34 int a; 35 B(int i){ 36 A(); 37 a = i; 38 } 39 40 void fun(){ 41 cout << a << endl; //正确,public成员。 42 cout << a1 << endl; //正确,基类的public成员,在派生类中变成了protected,可以被派生类访问。 43 cout << a2 << endl; //正确,基类的protected成员,在派生类中还是protected,可以被派生类访问。 44 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 45 } 46 }; 47 48 int main(){
53 B b(10); 54 cout << b.a << endl; //正确。public成员 55 cout << b.a1 << endl; //错误,protected成员不能在类外访问。 56 cout << b.a2 << endl; //错误,protected成员不能在类外访问。 57 cout << b.a3 << endl; //错误,private成员不能在类外访问。 58 59 system("pause"); 60 return 0; 61 }
3.private继承:
1 #include<iostream> 2 #include<assert.h> 3 using namespace std; 4 5 class A{ 6 public: 7 8 int a; 9 10 A(){ 11 a1 = 1; 12 a2 = 2; 13 a3 = 3; 14 a = 4; 15 } 16 17 void fun(){ 18 cout << a << endl; //正确 19 cout << a1 << endl; //正确 20 cout << a2 << endl; //正确 21 cout << a3 << endl; //正确 22 } 23 24 public: 25 int a1; 26 protected: 27 int a2; 28 private: 29 int a3; 30 }; 31 32 class B : private A{ 33 public: 34 int a; 35 B(int i){ 36 A(); 37 a = i; 38 } 39 40 void fun(){ 41 cout << a << endl; //正确,public成员。 42 cout << a1 << endl; //正确,基类public成员,在派生类中变成了private,可以被派生类访问。 43 cout << a2 << endl; //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。 44 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 45 } 46 }; 47 48 int main(){ 49 50 53 B b(10); 54 cout << b.a << endl; //正确。public成员 55 cout << b.a1 << endl; //错误,private成员不能在类外访问。 56 cout << b.a2 << endl; //错误, private成员不能在类外访问。 57 cout << b.a3 << endl; //错误,private成员不能在类外访问。 58 59 system("pause"); 60 return 0; 61 }
通过以上的代码,应该能够理解了。仔细看代码中派生类B中定义了和基类同名的成员a,此时基类的a仍然存在,可以验证。
int main(){ cout << sizeof(A) << endl; cout << sizeof(B) << endl; system("pause"); return 0; }
输出
16
20
所以派生类包含了基类所有成员以及新增的成员,同名的成员被隐藏起来,调用的时候只会调用派生类中的成员。
如果要调用基类的同名成员,可以用以下方法:
1 int main(){ 2 3 B b(10); 4 cout << b.a << endl; 5 cout << b.A::a << endl; 6 7 system("pause"); 8 return 0; 9 }
输出:
10
4
记得这里实在类外访问,而a在基类中是public,所以继承方式应该为public,使得a在派生类中仍然为public,在类外可以访问。