如果我有一个抽象类
像这样:
#pragma once
#include <string>
class BaseObject
{
public:
virtual std::string to_string() = 0;
};
一些类扩展了这个类。
#pragma once
#include "baseobject.h"
class Point : BaseObject
{
public:
Point() {}
~Point() {}
Point(float _x, float _y) : x(_x), y(_y) {}
std::string to_string();
float x, y;
};
在同一个项目中,我可以实现 to_string
的功能在派生类的 cpp 文件中,但是当我想在同一解决方案的另一个项目中使用此类时,出现链接器错误
error LNK2001: unresolved external symbol "public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Point::to_string(void)" (?to_string@Point@@UEAA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
1>path\to\CircleHT_Test.exe : fatal error LNK1120: 1 unresolved externals
一旦我将实现移动到头文件中,一切都很好。为什么是这样?我应该始终在派生类的 header 中实现纯虚函数吗?
最佳答案
Within the same project I can have the function implementation of
to_string
in the cpp file of the extension class but when I want to use this class in another project in the same solution I get a linker error.
Point::to_string
的实现源代码在某个实现文件中,大概叫做point.cpp
。该文件包含在项目的源文件列表中。因此,当您构建项目时,它会被编译成一个 point.obj
文件,其中包含该函数的二进制代码。该文件最终由链接器用来生成可执行程序。
当您构建不同的项目时,point.cpp
不在源文件列表中。您在某处包含 point.h
的事实无关紧要。将类分成*.cpp
和*.h
文件是只是一个非常普遍的约定。如果你只是包含了*.h
文件,并没有确保相应的*.cpp
文件被编译成*.obj
文件,那么结果正是您在这里遇到的情况:没有创建 point.obj
,因此链接器正确地提示缺少定义。
最简洁的解决方案是将第一个项目或第一个项目的一部分转换为一个库项目,该项目被构建到一个*.lib
文件中。然后应将该 *.lib
文件添加到需要它的每个应用程序项目的链接器依赖项中。
once I move the implementation to the header file it's all good. Why is this?
因为在那种情况下,函数的实现是内联的,并且包含头文件的其他项目中的每个 *.cpp
文件都会获取它。
最后,请注意这个答案在某种程度上特定于 Visual Studio/Visual C++,尽管构建过程的基本思想通常对于每个工具集都是相同的。
关于c++ - 在另一个项目中包含继承类时出现抽象类的链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42887223/