[英]Make base class pointer behave like derived class in C++
如果我從Shape基類中創建一個指針,如何使其表現得像circle(派生)類一樣? 這是我的班級定義:
//CShape.h class definition
//Shape class definition
#ifndef CSHAPE_H
#define CSHAPE_H
class CShape
{
protected:
float area;
virtual void calcArea();
public:
float getArea()
{
return area;
}
};
class CCircle : public CShape
{
protected:
int centerX;
int centerY;
float radius;
void calcArea()
{
area = float(M_PI * (radius * radius));
}
public:
CCircle(int pCenterX, int pCenterY, float pRadius)
{
centerX = pCenterX;
centerY = pCenterY;
radius = pRadius;
}
float getRadius()
{
return radius;
}
};
在我要調用這些對象的項目文件中,我有以下代碼:
CShape *basePtr = new CCircle(1, 2, 3.3);
basePtr->getRadius();
在我看來,這應該可行,但是我被告知CShape沒有成員“ getRadius()”。
編輯根據下面的響應,我試圖將basePtr對象動態_投射到CCircle中,如下所示:
CCircle *circle = new CCircle(1, 2, 3.3);
basePtr = dynamic_cast<CCircle *>(circle);
但是,這也失敗了。 我從沒做過dynamic_cast,也不熟悉C ++中的大多數語法,因此非常感謝您的幫助。
您可能要謹慎使用演員表。 首先, dynamic_cast
增加了運行時開銷,以檢查指針的類型(請參閱rtti )。 static_cast
便宜很多,但不檢查對象的動態類型。
垂頭喪氣是您的設計中可能有問題的指示! 絕對不是這種情況,但是特別是如果您正在學習C ++ OOP,請嘗試避免這種情況。
由於將getRadius
添加到CShape
沒有意義(僅因為並非所有形狀都具有半徑),所以處理CShape*
的函數不應依賴於對象為CCircle
。
例如,您可能試圖確定形狀的區域。 這對於所有形狀都可能是有意義的事情,因此您將添加一個virtual
抽象函數來計算形狀的面積。 然后,您的圓將通過使用其半徑來實現此效果,並通過使用其邊長的乘積來實現一個矩形等等。
編輯:了解原因
CShape *basePtr = new CCircle(1, 2, 3.3);
basePtr->getRadius();
無法工作,您必須了解C ++是強類型的。 在第二行中,您嘗試從CShape
訪問名為getRadius
的成員。 該類(及其任何父類)都沒有這樣的成員。 的確(在程序運行時)變量basePtr
指向類型為CCircle
的對象,但是在編譯時無法得知(通常是這樣)。 因此,C ++甚至不必費心檢查派生類型,因為(再次,通常)它根本無法檢查派生類型。 編譯此行時,它可能甚至不知道所有派生類型,因此它沒有機會了解您的意圖。
至於編譯器而言, basePtr
可以在一個對象,它不具有的類型,被人指指點點getRadius
成員。
要獲取getRadius
函數,必須將其聲明為CCircle
類型:
CCircle *basePtr = new CCircle(1, 2, 3.3);
basePtr->getRadius();
否則,如果你想聲明basePtr
為CShape
,使用動態與結合dynamic_cast
或使用C風格的直接澆鑄,作為@Janisz指出。
CShape *basePtr = new CCircle(1, 2, 3.3);
CCircle *child
// choose one of the two ways, either this:
child = (CCircle*)basePtr; // C-style cast
// or this:
child = dynamic_cast<CCircle*>(basePtr); // C++ version
child->getRadius();
您可以從CShape到Circle進行靜態轉換( http://www.cplusplus.com/doc/tutorial/typecasting/ )
另外,您可以在CShape中將getRadius()聲明為虛函數,在給出類名的情況下,您可能不想這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.