C++:基類與派生類對象之間的賦值兼容關系


4.5 基類與派生類對象之間的賦值兼容關系
在一定條件下,不同類型的數據之間可以進行類型轉換,例如可以將整型數據賦給雙精度型變量。
在賦值之前,先把整型數據轉換為雙精度型數據,然后再把它雙精度型變量。這種不同類型之間的自動轉換,稱為賦值兼容。在基類和派生類對象之間也存在有賦值兼容關系,基類和派生類對象之間的賦值兼容規則是指在需要基類對象的任何地方,都可以使用公有派生類的對象來代替。因為,通過公有繼承,除了構造函數和析構函數外,派生類保留了基類其他的所有的成員。那么,派生類就具有基類的全部功能,凡是基類能夠實現的功能,公有派生類都能實現。我們可以將派生類對象的值賦給基類對象,在用到基類對象的時候可以用其子類對象代替。

例如,下面聲明的兩個類:

class Base{          //聲明基類 
         ...
      }; 
      class Derived:public Base{   //聲明基類Base的公有派生類Derived 
         ...
      };  

根據兼容規則,在基類Base的對象可以使用的任何地方,都可以用派生類Derived的對象來代替,
但只能使用從基類繼承來的成員。具體表現在以下幾個方面:

(1)派生類對象可以向基類對象賦值,即用派生類對象中從基類繼承來的數據成員,逐個賦值給基類對象的數據成員。

例如:

Base b; //定義基類Base的對象b
Derived d;  //定義基類Base的公有派生類Derived的對象d
b=d;           //用派生類Derived的對象d對基類Base的對象b進行賦值

這樣的賦值效果是:對象b中所有數據成員都將具有對象d中對應數據成員的值。

(2)派生類對象可以初始化基類對象的引用。例如:
Base b; //定義基類Base的對象b
Derived d; //定義基類Base的公有派生類Derived的對象d
Base &br=d; //定義基類Base的對象的引用br,並用派生類Derived的對象對其進行初始化

(3)派生類對象地址可以賦值給指向基類對象的指針。例如:
Derived d; //定義基類Base的公有派生類Derived的對象b
Base *bp=&d; //把派生類對象的地址&d賦值給指向基類的指針bp,也就是說使指向基類
                         //對象的指針bp也可以指向派生類對象d

(4)如果函數的形參是基類對象或基類對象的引用,在調用函數時可以將派生類對象作為實參。例如:
class Base{ //聲明基類Base
       public:
               int i;
               ...
};
class Derived:public Base{ //聲明Base的公有派生類Derived
              ...
};
void fun(Base &bb)
{
              cout<<bb.i<<endl; //輸出該引用所代表的對象的數據成員i
}

在調用函數fun時,可以用派生類Derived的對象d4作為實參:
fun(d4);
輸出派生類Derived的對象d4賦值給基類數據成員i的值。

//基類與派生類對象之間的交換

#include<iostream>
using namespace std; 
class Base{          //聲明基類Base 
 public:
    int i;
    Base(int x)     //基類Base的構造函數 
    {
     i = x;
    }
    Base(const Base &b)
    {
     cout<<"Base Copyconstructor"<<endl;
    }
    void show()     //成員函數 
    {
     cout<<"i="<<i<<endl;
    }
};
class Derived:public Base{     //聲明基類Base的公有派生類Derived 
  public:
    Derived(int x):Base(x)     //派生類的構造函數 
    {}
    Derived(const Derived &d):Base(d) 
    {
      cout<<"Derived Copyconstructor"<<endl;
    }     
}; 
void fun(Base &bb)           //普通函數,形參為基類對象的引用 
{
 cout<<bb.i<<endl;
} 
int main()
{
  Base b1(100);         //定義基類對象b1
  b1.show();
  Derived d1(11);       //定義派生類對象d1
  b1=d1;                //用派生類對象d1給基類對象b1賦值
  b1.show();
  
  Derived d2(22);       //定義派生類對象d2
  Base &b2=d2;          //用派生類對象d2來對基類對象的引用b2進行初始化
  b2.show(); 
  
  Derived d3(33);       //定義派生類對象d3
  Base *b3=&d3;         //把派生類對象的地址&d3賦值給指向基類對象的指針b3
  b3->show();
  
  Derived d4(44);       //定義派生類對象d4
  fun(d4);              //派生類對象d4作為函數fun的實參 
  
  Derived d6(d4);
  return 0;
}

/*
程序運行結果如下:
Base 100
Base 11 
Base 22 
Base 33
44
Base Copyconstructor
Derived Copyconstructor

說明:

(1)聲明為指向基類對象的指針可以指向它的公有派生類的對象,但不允許指向它的私有派生的對象。
          例如:
          class Base{
            ...
          };  
          class Derived:private Base{
            ...
          }; 
          int main()
          {
            Base op1,*ptr;  //定義基類Base的對象op1及其指向基類Base的指針ptr 
            Derived op2;    //定義派生類Derived的對象op2 
            ptr = &op1;     //將指針ptr指向基類Base對象op1 
            ptr = &op2;     //錯誤,不允許將指向基類Base的指針ptr指向它的私有派生類對象op2 
            ......
            return 0;
          }
          
    2)允許將一個聲明為指向基類的指針指向其公有派生類的對象,但是不能將一個聲明為指向派生類
         對象的指針指向其基類的一個對象。
         例如:
         class Base{
            ...
          };  
          class Derived:public Base{
            ...
          }; 
          int main()
          {
            Base obj1;            //定義基類Base的對象obj1
            Derived obj2,*ptr;    //定義派生類Derived的對象obj2及其指向派生類對象的指針ptr 
            ptr = &obj2;          //將指針ptr指向派生類Derived對象obj2 
            ptr = &op2;           //錯誤,不允許將指向派生類Derived指針ptr指向它的基類Base對象obj1 
            ......
            return 0;
          } 

 


免責聲明!

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



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