【问题标题】:C++ Pointers/ReferencesC++ 指针/引用
【发布时间】:2013-04-13 20:32:23
【问题描述】:

此代码从鼠标单击中获取坐标并创建一个新顶点;

void DrawingWidget::mousePressEvent(QMouseEvent *event){
   if(getCurrentState()==ADD_VERTEX){
      x=event->x();
      y=event->y();

      Vertex p1 {&x,&y};
      m_mainWindow->addVertex(p1);
      update();
   }
}

这是 Vertex 类代码:

class Vertex {

public:

   float *x = 0;
   float *y = 0;

   Vertex() = default;
   Vertex(float *nx, float *ny);
};

所有 Verces 都保存在列表中:

QList<Vector2> vertexList;

和addVertex(顶点顶点):

addVertex(Vertex vertex){
   vertexList << vertex;
}

基本上第一个顶点添加效果很好,但是当我尝试添加第二个顶点时(使用给定的方法),第一个顶点坐标被改变了。

注意! Vertex 类的坐标是有意的指针,因为通过使用另一种方法我正在改变它们的坐标。

我错过了什么?

【问题讨论】:

  • Re:“顶点类的坐标是有意的指针,因为通过使用另一种方法我正在改变它们的坐标。” - 等等,什么?您刚刚描述的内容没有任何内容需要将xy 指针指向float。老实说,xy 真的应该只是 Vertex 的直接成员,如果你想要健全的代码。
  • 没有什么说 event 变量在函数完成后将保持不变,并且您正在存储指向其值的指针。要么你会一直指向最新的值,要么你最终会指向垃圾值/释放的内存。这取决于发生的编译器/操作系统。摘要:不要那样做。
  • 考虑将 getter/setter 添加到 Vertex 并使用这些方法操作坐标,而不是存储指向某个外部作用域的指针,这可能会以未知方式更改这些坐标,甚至使这些指针无效导致崩溃。您当前的实现是在自找麻烦,它不安全、容易出错并且总体上设计糟糕。
  • QMouseEvent 的xy 是整数,因此没有必要将它们存储为浮点数。并且已经有一个类来存储整数坐标对:QPoint。如果你真的需要花车,有QVector2D

标签: c++ qt pointers reference


【解决方案1】:

您的代码中的xy 可能是DrawingWidget 的字段,而在Vertex 中,您始终存储指向相同变量(那些字段)的指针。因此,在 vertexList 中,指向相同字段的指针始终具有相同的值。
我不明白你为什么对你的代码行为感到惊讶。

【讨论】:

    【解决方案2】:

    您问题中的代码和您观察到的行为暗示您有这样的事情:

    class DrawingWidget
    {
    public:
        void mousePressEvent(QMouseEvent *event);
    private:
        float x;
        float y;
        // ...
    };
    

    当函数 mousePressEvent() 被调用时,您将新坐标分配给这些成员:

    void DrawingWidget::mousePressEvent(QMouseEvent *event){
       if(getCurrentState()==ADD_VERTEX){
          x=event->x();
          y=event->y();
    ...
    

    因此,每次按下鼠标时,都会覆盖旧坐标。现在,这可能不是问题,但是由于您添加到列表中的Vertexs 包含指向这些类成员的指针,而不是简单地存储坐标的副本,第一个顶点出现改变了坐标。

    解决这个问题的方法是根本不使用指针(至少对于您的类而言)!

    class Vertex
    {
    public:
        Vertex() : x(0.0f), y(0.0f) {}
        Vertex(float x, float y) : x(x), y(y) {}
    
        float getX() const { return x; }
        float getY() const { return y; }
    
        void setX(float x) { this->x = x; }
        void setY(float y) { this->y = y; }
    
    private:
       float x; // NOT pointers!
       float y;
    };
    
    class DrawingWidget
    {
    public:
        void mousePressEvent(QMouseEvent *event);
    private:
        //float x; // Not needed!
        //float y;
        // ...
    };
    
    void DrawingWidget::mousePressEvent(QMouseEvent *event) {
       if(getCurrentState()==ADD_VERTEX) {
          Vertex p1{event->x(), event->y()};
          m_mainWindow->addVertex(p1);
          update();
       }
    }
    

    【讨论】:

    • 那我怎样才能改变X和Y呢?
    • @Ricardo Simmus:您可以为 Vertex 编写 getter/setter 函数(参见更新的示例)。
    • @Ricardo Simmus:这根本不是一个愚蠢的问题。只是误入歧途。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 2019-05-20
    相关资源
    最近更新 更多