我正在尝试在Qt
中构建一个分组游戏克隆。我需要弄清楚我的球与QGraphicsItem
碰撞的类型。例如,如果我将球与墙碰撞,球就会反弹,如果它与砖碰撞,它必须反弹并摧毁砖。要找出它是什么类型QGraphicsItem
,我认为最好的方法是覆盖QGraphicsItem::type()
(如果这不是正确的方法,请告诉我!)。
在brick.h
的以下代码中,我将'Brick'设置为Type 3.现在,值3看起来非常麻烦。我更愿意用'#define'
#include <QGraphicsItem>
//should this #define be here?
//#define BRICK_SPRITE 3
class Brick : public QGraphicsItem
{
public:
Brick(const QPixmap& p, QGraphicsScene *scene = 0);
virtual QRectF boundingRect() const;
virtual void paint( QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget );
QPainterPath shape() const;
enum { Type = 3 }; //enum {Type = BRICK_SPRITE}
int type() const { return Type; }
private:
QPixmap pixmap;
};
放置声明'#define BRICK_SPRITE 3'的好位置在哪里?我在项目中有几个其他文件。我应该将所有定义放在单独的头文件中吗?
答案 0 :(得分:5)
为什么不使用Type
而不是3? c ++中的enum
可以隐式转换为int
如果确实想要一个新名称,我建议您使用const int
变量而不是#define
- 它是类型和命名空间安全的,而预处理器宏不是
类似的东西:
class Brick : public QGraphicsItem
{
static const int BRICK_SPRITE = 3;
// rest of the class definition
};
根据我能找到的文件,您使用枚举和覆盖type()
的方法确实是首选方法
答案 1 :(得分:5)
如果你想遵循Qt的约定,你可以从不用全部大写字母命名你的常量开始......他们不这样做。另外,正如@Atilla指出的那样,对常量使用预处理器宏不是惯用的C ++。有很多很好的理由,比如能够在调试器中看到值:
C++ - enum vs. const vs. #define
通常情况下,您可以找到一个对“拥有”常量有意义的类。当Qt实际上没有地方可以放置它时,它只会将内容放入命名空间Qt::
http://doc.qt.io/archives/qt-4.7/qt.html
因此,如果您发现Brick
拥有此值没有意义,那么您可以在程序中放置一个命名空间来放置这些内容。
我实际上不知道QGraphicsItem::type()
是标准的事情......没有遇到过它。您已经注意到in the documentation它说自定义用户类型应该从UserType + 1
开始......所以我肯定会遵循该规则。它说如果你打算使用qgraphicsitem_cast()
,你只需要这样做,所以也许我看过的例子不需要它。
Qt在声明常量的约定方面给表(我能想到的)带来的唯一不寻常的东西叫做Q_DECLARE_FLAGS,它可以在OR标记的情况下带来类型安全性:
http://doc.qt.io/archives/qt-4.7/qflags.html
所以如果你做的事情如下:
class Brick : public QGraphicsItem {
public:
static const int Type = UserType + 1;
enum BrickFlag {
DamagesBall = 0x1,
ContainsCoins = 0x2,
MultipleHits = 0x4
};
Q_DECLARE_FLAGS(BrickFlags, BrickFlag)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Brick::BrickFlags)
现在您有一个名为Brick::BrickFlags
的特殊安全类型,它不能(例如)与Brick::Type
一起进行OR运算。