[英]Covariant return type and type conversion
s->duplicate()
返回一個Box*
類型的對象,但我收到一個錯誤,用Box*
初始化它。 它看起來像是被轉換回Shape*
。 如果將協變返回類型轉換回基類指針,有什么意義?:
struct Shape
{
virtual Shape* duplicate()
{
return new Shape;
}
};
struct Box : Shape
{
virtual Box* duplicate()
{
return new Box;
}
};
int main()
{
Shape* s = new Box;
Box* b = s->duplicate();
}
錯誤:
main.cpp:22:12: error: cannot initialize a variable of type 'Box *' with an rvalue of type 'Shape *'
Box* b = s->duplicate();
^ ~~~~~~~~~~~~~~
1 error generated.
盡管Box::duplicate
是在運行時被調用(通過虛擬調度),盡管Box::duplicate
做重寫Shape::duplicate
(協變),雖然Box::duplicate
並返回Box*
,你仍然會得到一個Shape*
指針,因為你通過Shape*
指針調用duplicate()
,而Shape*
是Shape::duplicate()
的返回類型,編譯器只看到你調用Shape::duplicate
,而不是Box::duplicate
。
C ++無法動態選擇類型,因此這是它能做的最好的。 你的Box*
在Box::duplicate
出路上自動轉換為Shape*
。 正如Barry所說,“它仍然需要在編譯時進行編譯,在編譯時我們所知道的是它返回一個Shape*
”。
然后,要再次將其設置為Box*
,您需要顯式地轉換它(使用static_cast
或dynamic_cast
),因為不存在隱式下轉換。
[C++11: 10.3/7]:
重寫函數的返回類型應與重寫函數的返回類型相同,或者與函數類的協變相同。 [..]
[C++11: 10.3/8]:
如果返回類型D::f
從返回類型不同B::f
,在返回類型的類類型D::f
應的點處完全聲明D::f
或應為D
類。 當重寫函數被調用為重寫函數的最終覆蓋時,其結果將轉換為(靜態選擇的)重寫函數 (5.2.2) 返回的類型 。 [..]
在標准文本中,下面是一個相關的例子。
關鍵是不要這樣做:
Box* b = s->duplicate();
這顯然無法工作,因為Shape::duplicate()
返回一個Shape*
。 相反,如果您直接在Box
上調用duplicate()
,則接受Box*
:
Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.