Если вы определяете свободную (не член класса) функцию, она должна быть определена в отдельно откомпилированном файле .cpp или в заголовке с пометкой inline. Так что в вашем случае вы можете скомпилировать его так:
inline Vector3d cross(const Vector3d &v0, const Vector3d &v1) {
float x,y,z;
x = v0.y*v1.z-v0.z*v1.y;
y = v0.z*v1.x-v0.x*v1.z;
z = v0.x*v1.y-v0.y*v1.x;
return Vector3d(x,y,z);
}
Ошибка вызвана тем, что у вас есть определение функции в заголовке, но вы не отметили ее как встроенную. Если вы теперь включите этот заголовок в два файла, которые скомпилированы отдельно, то компоновщик при попытке связать скомпилированные объектные файлы выдаст ошибку, потому что тогда он увидит перекрестную функцию, определяемую дважды.
Это работает без явного помещения inline для функций-членов класса, потому что функции-члены, которые определены внутри определения класса, неявно встроены.
Тем не менее, вообще не стоит делать определения функций в заголовке. Если ваша функция будет зависеть от других типов, чем просто вектор (в вашем случае это нормально ИМХО, но это спорно, конечно, - некоторые люди не любят это), то вам необходимо будет включать в себя заголовки для этих типов. Это излишне раздувает код, который косвенно включен в ваш заголовок. Вместо этого в этих случаях вы бы поместили только объявление вашей функции внутри заголовка:
Vector3d cross(const Vector3d &v0, const Vector3d &v1);
Но определите это в файле .cpp, который компилируется отдельно. Затем, конечно, нужно вставить строку.
Позвольте мне добавить небольшой список определений и объявлений, просто чтобы прояснить, что означает объявление и определение для функций и классов. Обратите внимание, что каждое определение также является декларацией, но не наоборот:
// class _declaration_ of boo
class boo;
// class _definition_ of foo.
class foo {
// member function _declaration_ of bar
void bar();
// member function _definition_ of baz
void baz() { }
};
// function _definition_ of fuzz
inline void fuzz() { }
// function _declaration_ of fezz
void fezz();