簡體   English   中英

從基礎方法獲取派生類

[英]Getting derived class from base method

我有3類EntityCharacterItem 當我做

Character * Player = new Character(QRectF(0, 0, 50, 50), "player", theScene);
Player->setVelocityX(30)->setAttackPoint(10);

編譯器告知該error: 'class Entity' has no member named 'setAttackPoint' 我該如何使Entity* setVelocityX(qreal vx); 返回一個Character指針或一個Item指針?

class Entity : public QObject, public QGraphicsPolygonItem
{
    Q_OBJECT

    public:
        Entity();
        Entity(qreal x, qreal y, qreal w, qreal h, QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Entity(QRectF position, QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Entity(QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Entity* setVelocityX(qreal vx);
        // etc
}


class Character : public Entity
{
    Q_OBJECT

    public:
        Character(qreal x, qreal y, qreal w, qreal h, QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Character(QRectF position, QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Character(QString tag, QGraphicsScene *scene = 0, QGraphicsItem *parent = 0);
        Character* setAttackPoint(int attackPoint);
        //etc
}


class Item : public Entity
{
    Q_OBJECT

    public:
        enum ItemType{
            Consummable,
            Special,
            Weapon
        };

        Item(QString name, qreal x, qreal y, qreal w, qreal h,  QString tag = "item", QGraphicsScene *scene = 0, Character *parent = 0);
        Item* setOwner(Character* newOwner);
        //etc
}

如果您絕對確定類型(否則,請使用dynamic_cast並檢查結果指針是否為非nullptr):

reinterpret_cast< Character * >( Player->setVelocityX(30))->setAttackPoint(10)

另外,根據您的代碼,您是否可以代替,或者函數調用的順序是否重要?

Player->setAttackPoint(10)->setVelocityX(30)
Character* player = new Character(QRectF(0, 0, 50, 50), "player", theScene);
dynamic_cast<Character*>(player->setVelocityX(30))->setAttackPoint(10);

順便說一句,此方法類型不安全。 您需要添加一些控件。

通常, SETS方法用於設置一些值,而不是返回對象。

Character* player = new Character(QRectF(0, 0, 50, 50), "player", theScene);
Entity* playerEntity = player->setVelocityX(30);
Character* isCharacter = dynamic_cast<Character*>(playerEntity);
if(isCharacter) {
   isCharacter->setAttackPoint(10);
}

還有另一種方法可以實現您要執行的操作: 反復使用模板模式

基本思想是,基類具有一個模板參數,即派生類。 然后在每個派生類中實現一個非虛函數 ,然后可以使用static_cast這樣的調用(簡化的類布局):

Entity.h

#include <iostream>

template<class DERIVED_CLASS>
class Entity
{
public:
    void doStuff()
    {
        static_cast<DERIVED_CLASS*>(this)->doStuffDerived();
    }
};


class Character : public Entity<Character>
{
public:
    void doStuffDerived()
    {
        // implementation
        std::cout << "character\n";
    }
};


class Item : public Entity<Item>
{
public:

    void doStuffDerived()
    {
        // implementation
        std::cout << "item\n";
    }
};

main.cpp

#include "Entity.h"

int main()
{
    // Instantiate a n Item object
    Entity<Item> item;
    item.doStuff();
    // Instantiate a character object 
    Character character;
    character.doStuff();
}

使用這種方法,您實際上沒有虛擬函數調用的開銷,但是可以為每個實現實現不同的行為,這有點像虛擬函數(好的編譯器可以輕松地將此代碼優化為僅對派生類進行函數調用) 。

而且您也不必依賴reinterpret_cast,如果可能的話,也應該避免這樣做。

這里是更多信息: 奇怪地重復模板模式

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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