C++派生访问控制说明符

来源:互联网 发布:qq五笔mac版 编辑:程序博客网 时间:2024/05/17 22:54
访问说明符(public,protected,private)类型:
        类成员访问说明符
        继承访问说明符
 
继承访问说明符说明了派生类中基类部分成员的继承方式。
    (1)通过public继承:派生类中基类部分成员的访问说明符在基类中为public或protected的,在派生类中类型保持不变,private的成员不可访问。
   (2)通过protected继承:派生类中基类部分成员的访问说明符在基类中为public或protected的,在派生类中类型为protected,private的成员不可访问。
   (3)通过private继承:派生类中基类部分成员的访问说明符在基类中为public或protected的,在派生类中类型为private,private的成员不可访问。
         (不可访问是指不能直接通过子类访问,但可以通过父类的成员访问)

C++中的继承方式(public、private、protected)会影响子类的对外访问属性,判断某一句话,能否被访问:
1)看调用语句,这句话写在子类的内部、外部
2)看子类如何从父类继承(public、private、protected)
3)看父类中的访问级别(public、private、protected)

 

现在,假设将访问的用户分为2级:

1.类内访问(类的实现者)
2.类的用户(可以理解成通过类的对象来访问)(类的普通用户)
        注:类内访问主要是指类的成员函数
        对于1级用户来说,可以访问除不可访问外的所有(public,protected,private)成员。2级用户只能访问public的成员。

        (这里被访问的成员都是指类成员访问说明符修饰的类成员)

其实,还有第三种类的用户——派生类!

基类class Base:

[cpp] view plain copy
  1. class Base{  
  2. public:  
  3.     //Constructor  
  4.     Base():base_public_string("I'm base_public_string"),base_protected_string("I'm base_protected_string"),base_private_string("I'm base_private_string")  
  5.     {}  
  6.     Base(string pub, string pro, string pri) :base_public_string(pub), base_protected_string(pro), base_private_string(pri)  
  7.     {}  
  8.   
  9.     string base_public_string;      //public string member  
  10.   
  11. protected:  
  12.     string base_protected_string;   //protect string member  
  13. private:  
  14.     string base_private_string;     //private string member  
  15. };  
  16. //包括两个public的构造函数和3个string类型的成员(public,protected,private各一个)。  


通过public继承的类:

[cpp] view plain copy
  1. class PubDerv:public Base{  
  2. public:  
  3.        PubDerv():Base(){}  
  4.        PubDerv(std::string pub,std::string pro,std::string pri):Base(pub,pro,pri){}  
  5.        void pub_printParentMem()  
  6.        {  
  7.               std::cout<<base_public_string<<std::endl;  
  8.               std::cout<<base_protected_string<<std::endl;  
  9.               //std::cout<<base_private_string<<std::endl;//父类的私有成员不管以什么方式被继承都是不可访问  
  10.        }  
  11. protected:  
  12.        void pro_printParentMem()  
  13.        {  
  14.               std::cout<<base_public_string<<std::endl;  
  15.               std::cout<<base_protected_string<<std::endl;  
  16.               //std::cout<<base_private_string<<std::endl;  
  17.        }  
  18. private:  
  19.        void pri_printParentMem()  
  20.        {  
  21.               std::cout<<base_public_string<<std::endl;  
  22.               std::cout<<base_protected_string<<std::endl;  
  23.               //std::cout<<base_private_string<<std::endl;  
  24.        }  
  25. };  


通过protected继承的类:

[cpp] view plain copy
  1. class ProDerv:protected Base{  
  2. public:  
  3.        ProDerv():Base(){}  
  4.        ProDerv(std::string pub,std::string pro,std::string pri):Base(pub,pro,pri){}  
  5.        void pub_printParentMem()  
  6.        {  
  7.               std::cout<<base_public_string<<std::endl;  
  8.               std::cout<<base_protected_string<<std::endl;  
  9.               //std::cout<<base_private_string<<std::endl;  
  10.        }  
  11. protected:  
  12.        void pro_printParentMem()  
  13.        {  
  14.               std::cout<<base_public_string<<std::endl;  
  15.               std::cout<<base_protected_string<<std::endl;  
  16.               //std::cout<<base_private_string<<std::endl;  
  17.        }  
  18. private:  
  19.        void pri_printParentMem()  
  20.        {  
  21.               std::cout<<base_public_string<<std::endl;  
  22.               std::cout<<base_protected_string<<std::endl;  
  23.               //std::cout<<base_private_string<<std::endl;  
  24.        }  
  25. };  


通过private继承的类:

[cpp] view plain copy
  1. class PriDerv:private Base{  
  2. public:  
  3.        PriDerv():Base(){}  
  4.        PriDerv(std::string pub,std::string pro,std::string pri):Base(pub,pro,pri){}  
  5.        void pub_printParentMem()  
  6.        {  
  7.               std::cout<<base_public_string<<std::endl;  
  8.               std::cout<<base_protected_string<<std::endl;  
  9.               //std::cout<<base_private_string<<std::endl;  
  10.        }  
  11. protected:  
  12.        void pro_printParentMem()  
  13.        {  
  14.               std::cout<<base_public_string<<std::endl;  
  15.               std::cout<<base_protected_string<<std::endl;  
  16.               //std::cout<<base_private_string<<std::endl;  
  17.        }  
  18. private:  
  19.        void pri_printParentMem()  
  20.        {  
  21.               std::cout<<base_public_string<<std::endl;  
  22.               std::cout<<base_protected_string<<std::endl;  
  23.               //std::cout<<base_private_string<<std::endl;  
  24.        }  
  25. };  

       3个子类的3个打印函数都相同,都是访问父类的3个string成员变量。
 
第1级访问(类内访问):
1.不可访问成员:
       父类的私有成员不管以什么方式被继承都是不可访问。可以看到访问base_private_string的代码被注释掉了。因为如果不注释掉,由于不可访问的成员不能由子类直接访问,所以编译时会报错,如下:
 
以PubDerv为例,3个打印函数访问父类私有变量base_private_string,编译时报错
 
2.public,protected,private成员:
        而父类的公有成员和保护成员由于继承方式不同,在子类中的访问说明符也不同(具体见前面的表格),但是不管是继承下来后属于哪类,对于第1级访问来说,这些成员都能被访问。因此3个子类对父类的公有成员和保护成员都能访问(编译未出错已经说明问题)。


第2级访问(类的普通用户):

main.cpp:

[cpp] view plain copy
  1. void main()  
  2. {  
  3.        PubDerv pubDerv;  
  4.        ProDerv proDerv;  
  5.        PriDerv priDerv;  
  6.    
  7.        cout<<"pubDerv:"<<endl;  
  8.        cout<<pubDerv.base_public_string<<endl;  
  9.        cout<<pubDerv.base_protected_string<<endl;  
  10.        cout<<pubDerv.base_private_string<<endl;  
  11.         
  12.        /* 
  13.        cout<<"proDerv:"<<endl; 
  14.        cout<<proDerv.base_public_string<<endl; 
  15.        cout<<proDerv.base_protected_string<<endl; 
  16.        cout<<proDerv.base_private_string<<endl; 
  17.        */  
  18.    
  19.        /* 
  20.        cout<<"priDerv:"<<endl; 
  21.        cout<<priDerv.base_public_string<<endl; 
  22.        cout<<priDerv.base_protected_string<<endl; 
  23.        cout<<priDerv.base_private_string<<endl; 
  24.        */  
  25.    
  26.        /* 
  27.        cout<<"pubDerv:"<<endl; 
  28.        pubDerv.pub_printParentMem(); 
  29.        cout<<"proDerv:"<<endl; 
  30.        proDerv.pub_printParentMem(); 
  31.        cout<<"priDerv:"<<endl; 
  32.        priDerv.pub_printParentMem(); 
  33.        */  
  34. }  


        先试图通过PubDerv的对象访问从父类继承来的3个string,在编译前可以想象结果:由与第2级访问(类的普通用户)只能访问公有成员,而3个string中只有base_public_string继承之后认识公有的,所以对另外两个string的访问会报错。(注释掉则可顺利编译运行)
        对于proDerv,由于从父类继承来的是2个string为protected和1个为不可访问,因此都不能通过2级访问去访问。
        同理priDerv,由于从父类继承来的是2个string为private和1个为不可访问,也都不能通过2级访问去访问。
 
        若要通过2级访问访问除public和不可访问以外的成员,则只能通过2级访问访问public成员,间接通过1级访问(public成员)去访问。
   

关于protected成员的访问权限:

        在没有继承的情况下,protected跟private相同。在派生类的时候才出现分化。
        基类对象(自然在类外)不能访问基类的protected成员,派生类中可以访问基类的protected成员。也就是说private成员是不能被继承的,只有public,protected的成员才可以被继承。
        派生类对象如果要访问基类protected成员只有通过派生类对象,派生类不能访问基类对象的protected成员。
        请注意 drived class和drived object:派生类和派生类对象。第一点和第二点都是针对派生类来说的。
        对于第三点总结一句话:只有在派生类中才可以通过派生类对象访问基类的protected成员。

        在派生类内部直接访问protected成员和访问派生类对象基类的protected成员都是可行的。
        
        很多书上都说有派生类的情况下protected的访问权限同public。这种说法是不对的,类内部直接访问没什么区别,但是访问对象基类的protected成员只能是在该类的内部。
        这里只列举了只有一层继承的情况,如果有多重继承的情况,比如三层。那么。中间层的类的内部还可以访问第三层类对象的基类成员,但是不能访问第三层类自己的protected的成员

0 0