链接器在另一个项目中包含继承的类时与抽象类的错误

时间:2017-03-19 13:35:31

标签: c++ inheritance abstract-class

如果我有一个抽象类

像这样:

#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;
};

在同一个项目中,我可以在派生类的cpp文件中使用to_string的函数实现,但是当我想在同一个解决方案中的另一个项目中使用此类时,我会收到链接器错误

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

一旦我将实现移动到头文件,这一切都很好。为什么是这样?我是否应该始终在派生类的标题中实现纯虚函数?

1 个答案:

答案 0 :(得分:1)

  

在同一个项目中,我可以使用函数实现   to_string在扩展类的cpp文件中,但是在我想要的时候   在同一个解决方案的另一个项目中使用此类我得到一个链接器   错误。

Point::to_string实现的源代码位于某个实现文件中,可能称为point.cpp。该文件包含在项目的源文件列表中。在构建项目时,它会被编译为point.obj文件,其中包含该函数的二进制代码。反过来,该文件最终被链接器用于生成可执行程序。

构建其他项目时,point.cpp不在源文件列表中。您在某处包含point.h这一事实无关紧要。将类分为*.cpp*.h文件只是一种非常常见的约定。如果您只包含*.h文件并且不确保将相应的*.cpp文件编译为*.obj文件,则结果正是您在此处遇到的结果:否{{ 1}}已创建,因此,链接器正确地抱怨缺少定义。

最干净的解决方案是将第一个项目或第一个项目的一部分转换为库项目,该项目将内置到point.obj文件中。然后应该将*.lib文件添加到需要它的每个应用程序项目的链接器依赖项中。

  

一旦我将实现移动到头文件,它一切都很好。这是为什么?

因为在这种情况下,函数的实现是内联的,并且包含头文件的另一个项目中的每个*.lib文件都会获得它。

最后,请注意,这个答案有点特定于Visual Studio / Visual C ++,尽管构建过程的基本思想通常与每个工具集相同。