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

时间:2013-11-19 23:58:44

标签: c++ class

正如我在标题中指出的那样,这是一个令我困惑的问题,但我仍无法找到解决方法。

我创建了一个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;
}

提前致谢!

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

如果将二进制算术运算符实现为成员,则应考虑将运算符设为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 object\n";
    return Point
        (
            _id + "+" + p._id,
            _x+p._x,
            _y+p._y
        );
}

...创建一个具有所需值的合适临时字符串(我也替换了excessive use of std::endl)。

答案 2 :(得分:1)

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