private是自己私有的,protected是可以让孩子知道的,public是公开的
三种访问权限
public:可以被任意实体访问,数据成员和函数成员可在成员函数,友元,继承类中直接使用。亦可以作为接口,供类的用户使用
protected:只允许子类及本类的成员函数访问,在基类中用法同private,在类外不能被基类对象访问。在派生类中,用法同基类的public,其成员在类内可被其继承类对象访问使用,类外一样不可以。
private:成员只能由类成员(类内)和友元访问。在类外不能被本类对象访问,不能被继承类访问(无论何种继承),虽然作为继承类的私有成员,但在使用过程中,是通过调用基类的构造函数完成参数的传递的。继承类不能访问基类的私有成员
#include<iostream> #include<assert.h> using namespace std; class A{ public: int a; A(){ 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(){ A itema; itema.a = 10; //正确 itema.a1 = 20; //正确 itema.a2 = 30; //错误,类外不能访问protected成员 itema.a3 = 40; //错误,类外不能访问private成员 system("pause"); return 0; }
三种继承方式
public 继承
protect 继承
private 继承
组合结果
基类中 继承方式 子类中
public & public继承 => public
public & protected继承 => protected
public & private继承 = > private
protected & public继承 => protected
protected & protected继承 => protected
protected & private继承 = > private
private & public继承 => 子类无权访问
private & protected继承 => 子类无权访问
private & private继承 = > 子类无权访问
由以上组合结果可以看出
1、public继承不改变基类成员的访问权限
2、private继承使得基类所有成员在子类中的访问权限变为private
3、protected继承将基类中public成员变为子类的protected成员,其它成员的访问 权限不变。
4、基类中的private成员不受继承方式的影响,子类永远无权访问。
此外,在使用private继承时,还存在另外一种机制:准许访问 。
我们已经知道,在基类以private方式被继承时,其public和protected成员在子类中变为private成员。然而某些情况下,需要在子类中将一个或多个继承的成员恢复其在基类中的访问权限。
C++支持以两种方式实现该目的
方法一,使用using 语句,这是C++标准建议使用的方式
方法二,使用访问声明,形式为 base-class::member;, 位置在子类中适当的访问声明处。(注,只能恢复原有访问权限,而不能提高或降低访问权限)
为什么引入private,protected,public
1.类的一个特征就是封装,public和private作用就是实现这一目的。所以:用户代码(类外)可以访问public成员而不能访问private成员;private成员只能由类成员(类内)和友元访问。
2.类的另一个特征就是继承,protected的作用就是实现这一目的。所以:protected成员可以被派生类对象访问,不能被用户代码(类外)访问。
三种继承方式例子
public继承
#include<iostream> #include<assert.h> using namespace std; class A{ public: int a; A(){ 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 B : public A{ public: int a; B(int i){ A(); a = i; } void fun(){ cout << a << endl; //正确,public成员 cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。 cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 } }; int main(){ B b(10); cout << b.a << endl; cout << b.a1 << endl; //正确 cout << b.a2 << endl; //错误,类外不能访问protected成员 cout << b.a3 << endl; //错误,类外不能访问private成员 system("pause"); return 0; }
protected继承
#include<iostream> #include<assert.h> using namespace std; class A{ public: int a; A(){ 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 B : protected A{ public: int a; B(int i){ A(); a = i; } void fun(){ cout << a << endl; //正确,public成员。 cout << a1 << endl; //正确,基类的public成员,在派生类中变成了protected,可以被派生类访问。 cout << a2 << endl; //正确,基类的protected成员,在派生类中还是protected,可以被派生类访问。 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 } }; int main(){ B b(10); cout << b.a << endl; //正确。public成员 cout << b.a1 << endl; //错误,protected成员不能在类外访问。 cout << b.a2 << endl; //错误,protected成员不能在类外访问。 cout << b.a3 << endl; //错误,private成员不能在类外访问。 system("pause"); return 0; }
private继承
#include<iostream> #include<assert.h> using namespace std; class A{ public: int a; A(){ 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 B : private A{ public: int a; B(int i){ A(); a = i; } void fun(){ cout << a << endl; //正确,public成员。 cout << a1 << endl; //正确,基类public成员,在派生类中变成了private,可以被派生类访问。 cout << a2 << endl; //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。 cout << a3 << endl; //错误,基类的private成员不能被派生类访问。 } }; int main(){ B b(10); cout << b.a << endl; //正确。public成员 cout << b.a1 << endl; //错误,private成员不能在类外访问。 cout << b.a2 << endl; //错误, private成员不能在类外访问。 cout << b.a3 << endl; //错误,private成员不能在类外访问。 system("pause"); return 0; }
派生类同名成员隐藏
派生类B中定义了和基类同名的成员a,此时基类的a仍然存在,可以验证
所以派生类包含了基类所有成员以及新增的成员,同名的成员被隐藏起来,调用的时候只会调用派生类中的成员。
如果要调用基类的同名成员,可以用以下方法:
记得这里是在类外访问,而a在基类中是public,所以继承方式应该为public,使得a在派生类中仍然为public,在类外可以访问。
再谈protected:protected成员访问权限详解
《C++ Primer》的时候,其中关于protected 成员的描述是这样的:
protected Members
The protected access label can be thought of as a blend of private and public :
Like private members, protected members are inaccessible to users of the class.
Like public members, the protected members are accessible to classes derived from this class.
In addition, protected has another important property:
A derived object may access the protected members of its base class only through a derived
object. The derived class has no special access to the protected members of base type objects.
在没有继承的情况下,protected跟private相同。在派生类的时候才出现分化。
上面那段英文前两条都很好理解,基类对象不能访问基类的protected成员,派生类中可以访问基类的protected成员。也就是说private成员是不能被继承的,只有public,protected的成员才可以被继承。
就是最后一条有些迷惑人,派生类对象如果要访问基类protected成员只有通过派生类对象,派生类不能访问基类对象的protected成员。
请注意 drived class和drived object:派生类和派生类对象。第一点和第二点都是针对派生类来说的。
对于第三点总结一句话:只有在派生类中才可以通过派生类对象访问基类的protected成员。
#include <iostream> using namespace std; class Base { public: Base(){}; virtual ~Base(){}; protected: int int_pro; }; class A : public Base { public: A(){}; A(int da){ int_pro = da; } void Print(A &obj){ obj.int_pro = 24; } void PrintPro(){ cout << "The proteted data is " << int_pro << endl; } }; int main() { A aObj; A aObj2(5); aObj2.PrintPro(); aObj.Print(aObj2); aObj2.PrintPro(); //注释1 //aObj.int_pro = 8; system("pause"); }
编译运行结果如下:
The protected data is 5
The protected data is 24
可见,在派生类内部直接访问protected成员和访问派生类对象基类的protected成员都是可行的。但是若果解开注释1.就会编译报错。
很多书上都说有派生类的情况下protected的访问权限同public。这种说法是不对的,类内部直接访问没什么区别,但是访问对象基类的protected成员只能是在该类的内部。
我这里只列举了只有一层继承的情况,如果有多重继承的情况,比如三层。那么。中间层的类的内部还可以访问第三层类对象的基类成员,但是不能访问第三层类自己的protected的成员