从基本方法获取派生类

时间:2014-12-16 12:29:41

标签: c++ qt

我有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
}

3 个答案:

答案 0 :(得分:2)

如果你完全确定类型(否则使用dynamic_cast并检查结果指针是否为非nullptr):

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

另外,根据你的代码,你不能去,或者函数调用的顺序是否显着?

Player->setAttackPoint(10)->setVelocityX(30)

答案 1 :(得分:1)

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);
}

答案 2 :(得分:1)

还有另一种方法可以实现您想要做的事情: 严格重复的模板模式

基本思想是基类有一个模板参数,它是派生类。 然后在每个派生类中实现非虚函数,然后可以使用类似的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,如果可能的话也应该这样做。

以下是一些更多信息:Curiously recurring template pattern