[c++ primer plus]虛函數的返回類型協變

派生類轉換爲基類,hierarchy向上走,稱爲upcasting;基類轉換爲派生類,hierarchy向下走,稱爲downcasting。downcasting是不安全的,一般不被允許。

含有虛函數的類,編譯器給每個對象添加一個隱藏成員,該成員保存一個指向函數地址數組的指針。這個函數地址數組包含了類的所有虛函數地址。如果派生類覆蓋了基類的虛函數,那麼這個數組中相應的元素也被覆蓋;如果派生類增加了一個虛函數,那麼會在數組中增加一個元素。不管虛函數數目是1還是10,都只在對象中添加一個地址成員,只是表的大小不同而已。

返回類型協變

覆蓋要求函數具有完全相同的入參

一般覆蓋具有相同的返回值,否則會提示錯誤

virtual double area () const = 0;
virtual float area () const ; //編譯器提示錯誤,返回類型不同

這個規則對返回類型協變而言,則有所放鬆。覆蓋的返回值不區分基類或派生類。從語意上理解,一個派生類也是一個基類。如下:

   Class ShapeEditor {……};
Class Shape 
{
public:
    
virtual const ShapeEditor & getEditor () const = 0//Factory Method
}
;

Class Circle;
Class CircleEditor : 
public ShapeEditor { … };
Class Circle : Public Shape
{
public:
    
const CircleEditor &getEditor () const ;
}
;

 在這個例子中,注意CircleEditor必須在Circle::getEditor的聲明之前被完整地定義(而不能僅僅聲明),
因爲編譯器必須知道CircleEditor對象的佈局,才能執行適當的地址操縱,從而將一個CircleEditor引用
(或指針)轉換爲一個ShapeEditor引用(或指針)。

協變返回類型的優勢在於,總是可以在適當程度的抽象層面工作。若我們是處理Shape,將獲得一個抽象的ShapeEditor;若正在處理某種具體的形狀類型,比如Circle,我們就可以直接獲得CiecleEditor.協變返回機制將我們從這樣的一種處境解脫出來:不得不使用易於出錯的轉換操作來“重新”提供類型信息,而這種信息是一開始就不應該丟掉的:(那麼,對於友元,派生的operator+,怎麼樣調用基類的operator+呢?)

Shape * s = getACircleOrOtherShape ();
Const ShapeEditor 
&sed = s->getEditor();
Ciecle 
*=getACircle();
Const CircleEditor 
&ced = c->getEditor();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章