C++对类成员的访问控制有着严格的要求,它们通过访问控制符public, private以及protected来控制访问权限。其中public和private容易理解,而protected则稍微难以理解,读过C++ Primer一书的同学应该对以下这段话不陌生:
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访问控制符给出了三条准则。
1.准则一
如同private成员,protected成员对类的使用者(用户)来说是不可访问的。
有如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream> using namespace std; class Base { public: Base(int pm):public_member(pm),protected_member(pm),private_member(pm){}; int public_member; //public成员 protected: int protected_member; //protected成员 private: int private_member; //private成员 }; int main() { Base b(5); //用户访问protected成员,无法访问:编译失败 cout << "b.protected_member = " << b.protected_member << endl; //用户访问private成员,无法访问:编译失败 cout << "b.private_member = " << b.private_member << endl; //用户访问public成员,可以访问:编译通过 cout << "b.public_member = " << b.public_member << endl; return 0; } |
编译:
1 2 3 4 5 6 |
[root@localhost protected]# g++ -Wall -g protected_demo.cpp -o protected_demo protected_demo.cpp: In function ‘int main()’: protected_demo.cpp:10: error: ‘int Base::protected_member’ is protected protected_demo.cpp:19: error: within this context protected_demo.cpp:12: error: ‘int Base::private_member’ is private protected_demo.cpp:21: error: within this context |
由上可知,访问protected成员和private成员都会得到错误提示。
2.准则二
如同public成员,protected成员对派生类来说是可以访问的。
有如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <iostream> using namespace std; class Base { public: Base(){}; Base(int pm):public_member(pm),protected_member(pm),private_member(pm){}; int public_member; protected: int protected_member; private: int private_member; }; class Derived:public Base { public: Derived(){}; Derived(int pm){ public_member = pm; protected_member = pm; //派生类可以访问protected成员(限于派生类的成员或友员函数内) cout << "public_member = " << public_member << endl; cout << "protected_member = " << protected_member << endl; } //在非成员或友员作用域内,是无法访问的,该语句会报错 //protected_member = 5; }; int main() { Derived d(5); return 0; } |
编译、运行:
1 2 3 4 |
[root@localhost protected]# g++ -Wall -g protected_demo2.cpp -o protected_demo2 [root@localhost protected]# ./protected_demo2 public_member = 5 protected_member = 5 |
3.准则三
前两条准则比较容易理解,第三条则过于晦涩,很容易让人摸不着头脑。英文原文如下:
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成员,但也只能通过派生类对象去访问。
这句话换个说法就是:派生类的成员或友员函数只能通过派生类对象去访问基类的protected成员。注:重点是通过派生类对象访问,可以理解为访问的是派生类的成员(由基类继承而来)。重要的事情说三遍,派生类,派生类,派生类。
再看后一句:派生类是无法访问基类中的protected成员的。注:重点是基类中的protected成员,重要的事情说三遍,基类,基类,基类。
看下面示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#include <iostream> using namespace std; class Base { public: Base(){}; Base(int pm):protected_member(pm){}; protected: int protected_member; }; class Derived:public Base { public: Derived(){}; Derived(int pm):Base(pm){}; friend void test(Derived &d); friend void test(Base &b); }; //形参为派生类对象的test友员函数 void test(Derived &d) { d.protected_member = 12; cout << "protected_member = " << d.protected_member << endl; } //形参为基类对象的test友员函数 //编译不通过,派生类无法访问基类的protected成员 /*void test(Base &b) { b.protected_member = 12; cout << "protected_member = " << b.protected_member << endl; }*/ int main() { Derived d(5); //protected成员初始值为5 test(d); //改变protected成员的值(通过派生类对象) //test(Base&)函数无法编译通过 //Base b(5); //test(b); return 0; } |
编译、运行:
1 2 3 |
[root@localhost protected]# g++ -Wall -g protected_demo3.cpp -o protected_demo3 [root@localhost protected]# ./protected_demo3 protected_member = 12 |
再看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <iostream> using namespace std; class Base { public: Base(){}; protected: int protected_member; }; class Derived:public Base { public: Derived(){}; Base b; //test()为成员函数 void test(){ protected_member = 12; cout << "protected_member of Derived : " << protected_member << endl; //该句无法编译通过,派生类对法访问基类的protected成员 //b.protected_member = 12; //cout << "protected_member of Base: " << b.protected_member << endl; } }; int main() { Derived d; d.test(); return 0; } |
编译、运行:
1 2 3 |
[root@localhost protected]# g++ -Wall -g protected_demo4.cpp -o protected_demo4 [root@localhost protected]# ./protected_demo4 protected_member of Derived : 12 |