相信很多同学在刚接触c++时一定遇到了和我同样的问题:public、private、protected这三者在使用和访问上到底在哪些地方存在区别?看了很多大牛的博客,决定自己总结下,也分享给和一样同样努力奋斗的程序员。
C++是一种面向对象的语言,其最大的特点就是封装性、继承性。
关于封装性
public和private就是为了这一目的而存在的。用户代码(类外)允许访问public成员却不能访问private成员;private则只能有类内的成员和友元函数(类)访问。关于public和private举个不恰当的例子:public就像你家里的房子,别人是可以看的。而private则是家里的电视家具,只有你的家人(类内成员)或者朋友(友元函数(类))来看or使用。
关于继承性
protected是为这个目的存在的。为什么会有protected这个访问标号的存在呢?我们在使用派生类的时候又是后需要访问基类的private成员,但我们是没有办法做到的。如果把基类的成员设为public那么问题来了,我们并不希望用户代码(类外)进行访问。因此有了protected这个访问标号,他的存在巧妙地解决了上面的问题。基类的protected成员允许派生类访问但不允许用户代码(类外)访问。这里要注意的是允许派生类访问只是允许派生类类内(通过成员函数)访问,派生类实例化的对象是不能访问的。
#include<iostream>
#include<assert.h>
using namespace std;
class Base{
public:
int a;
Base(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确,类内访问
cout << a3 << endl; //正确,类内访问
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
int main(){
Base item;
item.a = 10; //正确
item.a1 = 20; //正确
item.a2 = 30; //错误,类外不能访问protected成员
item.a3 = 40; //错误,类外不能访问private成员
return 0;
}
关于继承的访问标号
我们知道关于类的继承形式是这样的:
class Base
{
public:
void size();
protected:
int i;
private:
int j;
}
class Dervied: public Base
{
public:
void num();
private:
int k;
}
Dervied继承了Base类,而Dervied:后面的public就是访问标号。
当然除了public继承还有private继承和protected继承,他们三者之间还是有很大区别的。
public继承:
基类成员保持自己的访问级别:基类的public成员为派生类的public成员,基类的protected成员为派生类的protected成员,基类的private成员仍为基类的private成员。
#include<iostream>
#include<assert.h>
using namespace std;
class Base{
public:
int a;
Base(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class Dervied : public Base{
public:
int a;
Dervied(int i){
Base();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员
cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。
cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
Dervied b(10);
cout << b.a << endl;
cout << b.a1 << endl; //正确
cout << b.a2 << endl; //错误,类外不能访问protected成员
cout << b.a3 << endl; //错误,类外不能访问private成员
return 0;
}
protected继承
基类的public和protected成员在派生类中都为protected成员,基类的private成员仍为基类的private成员。
#include<iostream>
#include<assert.h>
using namespace std;
class Base{
public:
int a;
Base(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class Dervied : public Base{
public:
int a;
Dervied(int i){
Base();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员
cout << a1 << endl; //正确,基类的public成员,在派生类中是protected成员。
cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
Dervied b(10);
cout << b.a << endl; //正确,public成员,在派生类定义了相同的public成员会覆盖掉基类的成员
cout << b.a1 << endl; //错误,类外不能访问protected成员
cout << b.a2 << endl; //错误,类外不能访问protected成员
cout << b.a3 << endl; //错误,类外不能访问private成员
return 0;
}
private继承
基类的所有成员在派生类中为private成员
#include<iostream>
#include<assert.h>
using namespace std;
class Base{
public:
int a;
Base(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class Dervied : public Base{
public:
int a;
Dervied(int i){
Base();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员
cout << a1 << endl; //正确,基类的public成员,在派生类中变成了private成员。
cout << a2 << endl; //正确,基类的protected成员,在派生类中变成了private可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
Dervied b(10);
cout << b.a << endl; //正确,public成员,在派生类定义了相同的public成员会覆盖掉基类的成员
cout << b.a1 << endl; //错误,类外不能访问private成员
cout << b.a2 << endl; //错误,类外不能访问private成员
cout << b.a3 << endl; //错误,类外不能访问private成员
return 0;
}
由上面三种继承我们可以看出,派生类可以进一步限制但不能放松对继承的成员的访问。
对于派生类的类内访问继承的访问标号是没有作用的,基类的public和protected可以正常访问,private不能访问。
对于派生类的类外访问继承的访问标号起了决定性的作用,只有继承后为public的成员才能在类内访问。
如果有错误希望批评指正,谢谢~
本博文的代码部分借鉴了http://www.jb51.net/article/54224.htm处的代码,对博主表示感谢。