VS2010中的运算符重载和LNK2019错误

时间:2011-10-22 02:41:18

标签: c++ visual-c++ operator-overloading

我正在写一个Point类,它包含三个浮点数,x y z,一些函数和重载运算符。我用以下形式编写了运算符:

inline Point Point::operator+ (Point point)
{
    return Point(x + point.x, y + point.y, z + point.z);
}

inline void Point::operator+= (Point point)
{
   x += point.x;
   y += point.y;
   z += point.z;
}

这是重载这些运算符的正确方法吗?我已经测试了它并且它有效但我已经看到了另一种形式:

inline Point& Point::operator+ (Point& point)
{
    return Point(x + point.x, y + point.y, z + point.z);
}

inline Point& Point::operator+= (Point& point)
{
    x += point.x;
    y += point.y;
    z += point.z;
        return *this;
}

这两种形式有什么区别?

此外,我可以使用我的Point.cpp文件中的运算符,但如果我尝试使用它在Main.cpp中说,我得到一个未解析的外部符号的lnk2019错误。奇怪的是,我的函数在定义文件之外工作。为了让这些操作符在他们定义的文件之外工作,我缺少什么?

2 个答案:

答案 0 :(得分:3)

第一个操作符应该是

inline Point Point::operator+ (const Point &point) const
{
    return Point(x + point.x, y + point.y, z + point.z);
}

它不应该返回引用,因为它除了构造一个新对象而不修改现有对象(一般的经验法则)。 const被添加到函数中,因为不应该修改它所调用的点。添加对点作为参数的引用,因此不会有不必要的副本

第二个应该是

inline Point& Point::operator+= (const Point& point)
{
    x += point.x;
    y += point.y;
    z += point.z;
    return *this;
}

因为它应该修改现有的点,所以它应该返回一个引用。 const被添加到参数中,因为它不应该被更改。函数本身不是const,因为它应该修改点本身。

您获得的链接器错误是因为内联。要么在头文件中提供完整的实现,要么删除内联。

答案 1 :(得分:2)

inline Point& Point::operator+ (Point& point)
{
    return Point(x + point.x, y + point.y, z + point.z);
}

这是错误的,它返回对函数返回时不再存在的临时引用的引用。如果你足够幸运,它会导致段错误。如果您尝试这样做,大多数编译器会给您一个警告。理想情况下,您可以将此运算符编写为自由函数,并根据您的成员operator+=实现。

inline Point& Point::operator+= (Point& point)
{
    x += point.x;
    y += point.y;
    z += point.z;
        return *this;
}

这几乎是首选方式,除了你应该将point作为const引用,否则你不能将它与temporaries一起使用。返回对自身的引用是允许链接运算符的原因。人们普遍认为,如果有疑问,可以像彗星那样做,并且贪婪地这样做。

总结一下,'cannonical'实现将是:

inline Point& Point::operator+=( Point const& point )
{
    x += point.x;
    y += point.y;
    z += point.z;
    return *this;
}

inline Point const operator+( Point left, Point const& right )
{
     return left += right;
}

请注意,operator+是一个自由函数,允许Point转换到两个操作数,而不仅仅是正确的操作数。它方便地用operator+=实现:左边的参数是按值获取的,以便有一个我们可以修改的临时副本,我们通过向它添加正确的参数来实现。由于operator+=返回一个引用,我们使用这样的返回来提供将作为函数结果复制的值。

相关问题