Reputation: 1331
I have 3 classes Entity
, Character
and Item
.
When I do
Character * Player = new Character(QRectF(0, 0, 50, 50), "player", theScene);
Player->setVelocityX(30)->setAttackPoint(10);
The compiler tells that error: 'class Entity' has no member named 'setAttackPoint'
.
How can I make Entity* setVelocityX(qreal vx);
return a Character
pointer or an Item
pointer?
.
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
}
Upvotes: 0
Views: 107
Reputation: 578
There is also another way of achieving what you want to do: Curriously Recurring Template Pattern
The basic idea is that the base class has a template parameter which is the derived class. Then you implement a non virtual function in every derived class which can then be called using a static_cast like that (simplified class layout):
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();
}
With this method you actually do not have the cost of a virtual function call but can implement a different behavior for every implementation which is kinda like a virtual function (a good compiler can easily optimize this code to only a function call on the derived class).
And you also do not have to rely on a reinterpret_cast, which should also be prevented if possible.
Here are some more informations: Curiously recurring template pattern
Upvotes: 1
Reputation: 21520
Character* player = new Character(QRectF(0, 0, 50, 50), "player", theScene);
dynamic_cast<Character*>(player->setVelocityX(30))->setAttackPoint(10);
By the way this method is not type safe. You need to add some controls.
Generally, SETS methods are used to set some value, not to return an object.
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);
}
Upvotes: 1
Reputation: 1729
If you are absolutely certain on the type (otherwise use dynamic_cast and check the resulting pointer for non-nullptr):
reinterpret_cast< Character * >( Player->setVelocityX(30))->setAttackPoint(10)
Also, based on your code, couldn't you go instead or is the order of the function calls significant?
Player->setAttackPoint(10)->setVelocityX(30)
Upvotes: 2