С++:функция заголовка неправильно связывается из библиотеки в exe

StackOverflow https://stackoverflow.com/questions/500182

  •  20-08-2019
  •  | 
  •  

Вопрос

У меня есть заголовочный файл в библиотеке (alibrary.lib).Библиотека является статической библиотекой (.lib) и правильно связана с exe.

Теперь у меня есть класс:Вектор3d.

class Vector3d 
{
    void amethod()
    {
       blah
    }

};

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

}

Vector3d объявлен и определен в заголовочном файле (Vector3d .h).После объявления класса я использую кросс-функцию.

Компиляция библиотеки представляет собой файл, но когда она ссылается на exe-файл модульного теста, я получаю эту ошибку:

 flywindow.obj :error LNK2005: "class Vector3d __cdecl cross(class Vector3d const &,class Vector3d const &)" (?cross@@YA?AVVector3d@@ABV1@0@Z) already defined in fly.obj

Есть идеи?

Спасибо

Это было полезно?

Решение

Если вы определяете свободную функцию (не член класса), ее необходимо определить в отдельно скомпилированном файле .cpp или в заголовке и пометить как встроенное.Итак, в вашем случае вы можете избежать компиляции следующим образом:

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

}

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

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

Однако, как правило, не рекомендуется делать определения функций в заголовке.Если ваша функция будет зависеть от других типов, а не только от вектора (в вашем случае это нормально, ИМХО, но это, конечно, спорно - некоторым это не нравится), тогда вам потребуется включить заголовки для этих типов.Это приведет к излишнему раздуванию кода, косвенно включенного в ваш заголовок.Вместо этого в этих случаях вы должны поместить в заголовок только объявление вашей функции:

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

Другие советы

Наиболее вероятное объяснение состоит в том, что у вас есть код (в частности, определение креста) в вашем включаемом файле, и ваш включаемый файл включается в два исходных файла, отсюда и двойное определение.

Заголовочные файлы должны содержать объявления, а не определения.Объявления (говорящие о том, что что-то существует) — это такие вещи, как typedef, объявления классов, перечисления и так далее.

Определения (придающие смысл существующим вещам) — это такие вещи, как функции, определения переменных и так далее.

Ваша кросс-функция должна быть объявлена ​​в заголовочном файле:

Vector3d cross(const Vector3d &v0, const Vector3d &v1);

но определено в отдельном исходном файле.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top