Перегрузка оператора и ошибка LNK2019 в VS2010 - PullRequest
0 голосов
/ 22 октября 2011

Я пишу класс 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 ]

3 голосов
/ 22 октября 2011

Первый оператор должен быть

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 добавляется к аргументу, потому что его нельзя менять.сама функция не является константной, потому что она должна изменять саму точку.

Ошибка компоновщика, которую вы получаете, из-за встроенного.либо предоставьте полную реализацию в заголовочном файле, либо удалите встроенный.

2 голосов
/ 22 октября 2011
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 в качестве константной ссылки, иначе вы не сможете использовать его с временными. Возвращение ссылки на себя - это то, что позволяет связывать операторов. Обычно говорят, что если сомневаешься, делай как целые, а целые как это.

Подводя итог, можно сказать, что "каноническая" реализация будет:

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+= возвращает ссылку, мы используем такой возврат, чтобы предоставить значение, которое будет скопировано как результат функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...