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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM