簡體   English   中英

使基類指針的行為類似於C ++中的派生類

[英]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();

否則,如果你想聲明basePtrCShape ,使用動態與結合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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM