C++:父对象在不调用方法的情况下更改其id属性

C++: Parent object change their id attribute without method call

本文关键字:情况下 属性 id 方法 对象 调用 C++      更新时间:2023-10-16

正如我在标题中所指出的,这是一个让我非常困惑的问题,但我仍然找不到解决办法。

我创建了一个Point类,它有三个私有属性(_id、_x和_y)以及相关的公共get和set方法。例如,我创建了三个点(G、H、R),其中点G是"父"。点H是点G(克隆)的原型,点R将是集合点(G+H)(点的相加)的结果。

点数样本:

    Point G ("pG", 3.5f, 6.5f);
    Point H (G.prototype ()); H.setId ("pH");
    Point R;
    R = G + H;

程序工作正常,但不幸的是,在操作{R=G+H}之后,点G的_id属性变成了点R的克隆属性,我不明白为什么会发生这种情况,因为评估是从右到左进行的(H+,+G,=R)。

问题是为什么G点属性会自行改变?

出现问题的代码:

#include <iostream>
#include <string>
using namespace std;
class Point
{
    private:
        string _id;
        double _x;
        double _y;
    public:
        Point(string id="undefined", double x = 0.00f, double y = 0.00f)
        :_id(id), _x(x), _y(y){}
        ~Point(){}
    public:
        // Getters methods
        string getId() const          { return _id;}
        double getX()  const          { return _x; }
        double getY()  const          { return _y; }
        void   setId(string id)       { _id = id; }
        // Setters methods
        void   setX(double n = 0.00f) { _x = n; }
        void   setY(double n = 0.00f) { _y = n; }
        Point  prototype()            { return Point(_id, _x, _y); }
        Point  operator+ (const Point& p)
        {
            cout << "Operator + called, returning a new object" << endl;
            return Point
            (
                _id.append("+").append(p._id),
                _x+p._x,
                _y+p._y
            );
        }
        Point operator= (const Point& p)
        {
            cout << "Operator = called, returning a new object Point(p._id, p._x, p._y)" << endl;
            _id=p._id;
            _x=p._x;
            _y=p._y;
            return *this;
        }
};
int main()
{
    Point G("G",10.0f, 10.0f);
    Point H(G.prototype()); H.setId("H");
    Point R;
    R = G + H;
    cout << "object Point {id: " << G.getId() << ", x: " << G.getX() << ", y: " << G.getY() << "}" << endl;
    cout << "object Point {id: " << H.getId() << ", x: " << H.getX() << ", y: " << H.getY() << "}" << endl;
    cout << "object Point {id: " << R.getId() << ", x: " << R.getX() << ", y: " << R.getY() << "}" << endl;
    return 0;
}

提前感谢!

 Point  operator+ (const Point& p)
 {
     cout << "Operator + called, returning a new object" << endl;
     return Point
       (
          _id.append("+").append(p._id),    // HERE
          _x+p._x,
          _y+p._y
       );
}

在此行中,修改this对象的_id属性。根据经验,binary+运算符应该是const成员,或者-IMO-cleaner-一个使用两个const引用参数的静态方法。

顺便说一句,您可以在C++中添加字符串,只需对它们应用+运算符(_id + "+" + p._id)。

如果将二进制算术运算符实现为成员,则应考虑将该运算符设为const成员。这将捕捉到实现中的明显修改(实现是越界的,以避免包含不相关的代码):

Point Point::operator+ (const Point& p) const
{
    cout << "Operator + called, returning a new object" << endl;
    return Point
        (
            _id.append("+").append(p._id),
            _x+p._x,
            _y+p._y
        );
}

操作_id.append("+")实际上对this->_id(即左手操作数的_id成员)进行操作。由于您的成员运算符不是const,因此编译器允许您进行修改。这可能不是你想要做的。你可能更想写:

Point Point::operator+ (const Point& p) const
{
    cout << "Operator + called, returning a new objectn";
    return Point
        (
            _id + "+" + p._id,
            _x+p._x,
            _y+p._y
        );
}

其创建具有期望值的合适的临时字符串(我还替换了std::endl的过度使用)。

operator+过载中的此行:

_id.append("+").append(p._id),

在这里,您必须非常小心,您当前处于一个对象中(在您的示例中,这将是G对象)。append实际上改变了本地字符串,所以您的代码是先附加+,然后再附加p._id,然后将其深度复制到返回值中。

一个快速的解决方案是将其更改为临时的,以容纳您需要的东西:

_id + "+" + p._id

为了避免将来出现这样的问题,您应该将运算符重载声明为友元方法,这样就可以非常清楚地了解您在操作什么

friend Point  operator+ (const Point& lhs, const Point& rhs)
{
    cout << "Operator + called, returning a new object" << endl;
    return Point
    (
        lhs._id.append("+").append(rhs._id), //COMPILER ERROR!  We're modifying the const "lhs"!
        lhs._x+rhs._x,
        lhs._y+rhs._y
    );
}

因此,让我们将其更改为:

friend Point  operator+ (const Point& lhs, const Point& rhs)
{
    cout << "Operator + called, returning a new object" << endl;
    return Point
    (
        lhs._id + "+" + rhs._id, // no longer modifying lhs -- all is well!
        lhs._x+rhs._x,
        lhs._y+rhs._y
    );
}
相关文章: