zoukankan      html  css  js  c++  java
  • c/c++ 继承与多态 由子类向父类的转换规则

    问题1:子类B可以有3种方式(public, protected, private)继承父类A,用哪种方式继承,用户代码才能把子类B的对象转换成父类A的对象呢?

    只用当子类B以public方式继承父类A后,在用户代码里,才能把子类B的对象转换成父类A的对象。

    原因如下:

    • 下面例子的类Pro_derv和类Pri_derv,分别是以protected和 private的方式继承了Base,所以在类Pro_derv和类Pri_derv对象里,原来在Base类里的成员pub_mem()已经不是public的属性了,而分别是protected和 private的属性了,protected和 private属性的成员对于用户程序来说是不可访问的。
    • 当创建了Pro_derv和类Pri_derv的对象后,成员pub_mem()已经是分别是protected和 private的属性了。所以类Pro_derv和类Pri_derv的用户程序是不可以访问protected或者 private属性的成员pub_mem()的。
    • 当要把类Pro_derv和类Pri_derv的对象转换成父类Base类的对象的时候,从类Base的角度看,pub_mem()是public的成员,所以类Base的用户程序是可以访问pub_mem()的,但是从类Pro_derv和类Pri_derv的角度看,pub_mem()已经不是public的成员了,所以类Pro_derv和类Pri_derv的用户程序是不可以访问成员pub_mem()的。这时,编译器就很困惑这个矛盾了,所以编译器干脆就不让你编译通过。。。
    class Base{
    public:
      void pub_mem();
    protected:
      int prot_mem;
    private:
      char pri_mem;
    };
    
    class Pub_derv : public Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pro_derv : protected Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pri_derv : private Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
    };
    
    
    int main(){
      Pub_derv pub;
      Pro_derv pro;
      Pri_derv pri;
      
      Base& b1 = pub;
      Base& b2 = pro;//error
      Base& b3 = pri;//error
    }
    

    github

    问题2:子类B可以有3种方式(public, protected, private)继承父类A,用哪种方式继承,在子类B的成员函数和子类B的友元(非用户代码)里才能把子类B的对象转换成父类A的对象呢?

    不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元里(非用户代码),都能把子类B的对象转换成父类A的对象。

    原因如下:

    - 不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元(非用户代码)里,父类A的所以成员的属性是不发生变化的,所以转化后,还是可以用父类A的对象,访问父类A的public成员。
    class Base{
    public:
      void pub_mem();
    protected:
      int prot_mem;
    private:
      char pri_mem;
    };
    
    class Pub_derv : public Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pro_derv : protected Base{
      friend void pro_fri(Pro_derv&);
      int f(){
        Base& b = *this;//不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元(非用户代码)里,都能把子类B的对象转换成父类A的对象。
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pri_derv : private Base{
      friend void pri_fri(Pri_derv&);
      int f(){
        Base& b = *this;//不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元(非用户代码)里,都能把子类B的对象转换成父类A的对象。
        pub_mem();
        return prot_mem;
      }
    };
    
    void pro_fri(Pro_derv& pro){
      Base& b = pro;//不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元(非用户代码)里,都能把子类B的对象转换成父类A的对象。
    }
    
    void pri_fri(Pri_derv& pro){
      Base& b = pro;//不论子类B以何种方式继承父类A,在子类B的成员函数和子类B的友元(非用户代码)里,都能把子类B的对象转换成父类A的对象。
    }
    int main(){
      Pub_derv pub;
      Pro_derv pro;
      Pri_derv pri;
      
      Base& b1 = pub;
      //Base& b2 = pro;
      //Base& b3 = pri;
    }
    
    

    github

    问题3:子类B可以有3种方式(public, protected, private)继承父类A,用哪种方式继承,子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象呢?

    只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象。

    class Base{
    public:
      void pub_mem();
    protected:
      int prot_mem;
    private:
      char pri_mem;
    };
    
    class Pub_derv : public Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pro_derv : protected Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pri_derv : private Base{
      int f(){
        pub_mem();
        return prot_mem;
      }
    };
    
    
    class Pub_Pub_derv : private Pub_derv{
      friend void pubpubfri(Pub_Pub_derv&);
      int f(){
        Base& b = *this;//只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pro_Pro_derv : private Pro_derv{
      friend void proprofri(Pro_derv&);
      int f(){
        Base& b = *this;//只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
        pub_mem();
        return prot_mem;
      }
      //char g(){return pri_mem;}//error
    };
    
    class Pri_Pri_derv : private Pri_derv{
      friend void priprifri(Pri_derv&);
      int f(){
        //Base* b = *this;//error,只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
        //pub_mem();
        //return prot_mem;
      }
    };
    
    void pubpubfri(Pub_derv& pd){
      Base& b = pd;//只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
    }
    void proprofri(Pro_derv& pd){
      Base& b = pd;//只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
    }
    void priprifri(Pri_derv& pd){
      //Base& b = pd;//error,只用当子类B以public或者protected方式继承父类A后,在子类B的子类C的成员函数和子类B的子类C的友元里,才能把子类B的对象转换成父类A的对象
    }
    int main(){
      Pub_derv pub;
      Pro_derv pro;
      Pri_derv pri;
      
      Base& b1 = pub;
      //Base& b2 = pro;
      //Base& b3 = pri;
    }
    
    

    github

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    [android] AndroidManifest.xml
    [android] AndroidManifest.xml【 manifest -> permission-tree 和 manifest -> permission-group】
    [android] AndroidManifest.xml
    [android] AndroidManifest.xml【 manifest -> uses-permission】
    [android] AndroidManifest.xml -【manifest】
    [maven] 详解
    [velocity] velocity详解
    [Java] java调用wsdl接口
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10208113.html
Copyright © 2011-2022 走看看