C++继承体系访问权限

  1. 基类中的protected数据成员

    派生类的成员或友员只能通过派生类对象访问基类的受保护成员

    例如:

    class Son{
    protected:
        int money;
    };
    class Father:public Son{
    friend void getInfo(Father& f);   //能通过派生类访问基类的受保护成员(即f.money是正确的)
    friend void getInfo2(Son &s);     //不能通过基类访问基类的受保护成员
        //根本原因是友员函数和友员类不具有传递性和相对性,getInfo和getInfo2只是派生类的友元函数,所以能通过它去访问受保护成员变量,但不是Son的友元函数,不能访问它的受保护成员
    };
  2. 公有、私有和受保护继承—>访问说明符

    class Son{
       private:
           int money = 100;
       public:
           int sex = 1;
       protected:
           int age = 22;
       public:
           int getSex(){
               return sex;
           }
    };
    //Father派生类是私有访问符
    class Father:private Son
    {
       public:
           int getAge(){
               return age;
           }
    };   
    //Monther是公有访问符
    class Monther:public Son
    {
       public:
           int getAge(){
               return age;
           }
    };
    
    int main(void){
        //派生访问说明符对于访问基类的数据成员没有影响,依旧是由基类成员的访问修饰符决定的
    Monther m;
        cout << m.sex << endl;
    cout << m.getAge() << endl;  
    Father f;
        cout << f.getAge() << endl;
    cout << f.getAge() << endl;
        //主要是控制派生类用户对基类成员的访问权限,对于public的Monther来说无影响,但对于priate的Father来说它继承自基类的非private的成员都是私有的(即Son的非private的成员会在Father内部私有化)
    cout << m.getSex() << endl;
    cout << f.getSex() << endl;//可以在Father类内部调用它的private的getSex方法,但不能在外部调用
    }
  3. 默认的继承保护级别

    class Base{/**/};
    //默认派生运算符由定义派生类所用的关键字决定(struct中的成员默认public,class默认private)
    struct F1 : Base {/**/};             //默认public继承
    class F2 : Base {/**/};                  //默认private继承
  4. 派生类到基类的隐式转换

    1. 对于类的调用者(用户)来说,只有当派生类public继承基类时,才能在用户代码中实现从派生类到基类的隐式转换
    2. 无论派生类以何种方式继承基类的,派生类的成员函数和友员(在派生类的内部而不是用户代码中)都可以使用派生类到基类的隐式类型转换
    3. 只有派生类是public或者protected方式继承基类时,派生类的派生类的成员和友员才能完成派生类到基类的转换
  5. 友员是不可以传递和继承的

    派生类的友员不能随意访问基类的成员(可以通过派生类对象访问),基类的友员也不能随意访问派生类,每个类负责控制自己的成员的访问权限,就像每个类负责自己成员的初始化一样

    class Son{
       protected:
           int age = 22;
       public:
           int getSex(){
               return sex;
           }
    };
    //Father派生类是私有访问符
    class Father:private Son
    {
       public:
            using Son::getSex;  //通过using声明可以使Father的用户可以访问到getSex
           int getAge(){
               return age;
           }
    };

    派生类只能为那些它可以访问到的名字提供using声明

    并且using声明中的成员的访问权限由using前的那个访问修饰符决定,例子中的using Son::getSex 是public的,所以可以被Father的所有用户及其自身访问到getSex;如果是private的,则只能被Father及其友员访问;protected还可以被其派生类访问

  6. 同JAVA一样,派生类向上转型以后,只能访问基类拥有的成员函数,而不能去访问派生类特有的成员函数(编译器就会检查出来),向上转型是安全的,向下转型是危险的,需要强制类型转换,但向下转型因为对于基类来说可能会比派生类少一些方法,这些编译器不能检查出来,如果运行时访问的话会出错

  7. 派生类成员会隐藏同名的基类成员,派生类的作用域嵌套在基类的作用域内

    调用派生类成员时

    1. 首先会在派生类中查找
    2. 派生类中没有会去基类中查找
    3. 根据静态类型进行编译时的常规检查匹配(名字查找优于类型检查,所以如果在派生类中定义了一个和基类中同名但是参数列表不同的成员,则基类的成员会被隐藏,编译器检查时发现同名但是参数列表不匹配就会报错,并不会调用基类的成员),根据动态类型确定调用哪个版本的成员函数。

    如同隐藏虚函数一样,我们可以使用作用域运算符覆盖掉原有的查找规则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值