【问题标题】:Linker error when inlining function from cpp file从 cpp 文件内联函数时出现链接器错误
【发布时间】:2011-05-12 08:44:56
【问题描述】:

我在执行以下操作时遇到链接器(未解析的外部符号)错误:

-我有一个类“Object”——它在“object.h”中定义。

它有一个构造函数,例如:explicit Object(double x, /* lots more */);

在文件“object.cpp”中,我想给构造函数一个主体:Object::object(double x) : _x(x) {}

这可行.. 但是,如果我在“object.cpp”文件中添加关键字“inline”:

inline Object::Object(double x) : _x(x) {}

突然出现链接器错误! “错误 LNK2019:无法解析的外部符号”

为什么? - 这是否意味着我不能对构造函数使用内联?

编辑:实际上我注意到所有方法都是如此。 但是如果我将所有方法移到 object.h 标头文件中,它确实可以工作。您不能从定义对象的头文件外部内联函数吗?

EDIT2:好吧,一个大更新,我决定构建一个快速测试用例:
ma​​in.cpp

#include "a.h"
int main ()
{
    a t;
    t.test(5);
    return 0;
}

啊.h

class a {
public:
    void test (int x);
};

a.cpp

#include <iostream>
#include "a.h"
inline void a::test(int x) {
    std::cout << x << std::endl;
}

这会产生以下错误:

main.obj : 错误 LNK2019: 函数 _main 中引用的未解析外部符号“public: void __thiscall a::test(int)” (?test@a@@QAEXH@Z)

删除“inline”关键字使程序工作。将“a.h”和“a.cpp”合并到一个文件中也是如此。

我实在想不出更多信息可以提供:/

【问题讨论】:

  • 看看这个关于内联类成员函数的讨论——它可能会帮助你理解为什么一个或另一个案例会失败。 msdn.microsoft.com/en-us/library/bw1hbe6y.aspx
  • 我不认为inline 意味着你认为的意思。你能说说你为什么要努力实现它吗?

标签: c++ linker-errors unresolved-external


【解决方案1】:

您需要了解标记为inline 的函数的定义规则。

标记函数inline 意味着您可以在程序中的多个翻译单元中定义该函数(但每个翻译单元只能定义一次),但所有定义必须相同并且您必须在使用该函数的每个翻译单元中提供一个定义。

在您的示例中,main.cpp 的翻译单元使用 a::test(int),但该翻译单元中没有定义。 a.cpp 的翻译单元中有一个定义,但这里标记为 inline,这意味着您不能在 main.cpp 的翻译单元之外留下定义。

我不确定您为什么要将inline 添加到a.cpp 的定义中,因为它没有必要也没有用。 inline 允许您将函数定义放在共享头文件中,但如果您想将函数放在源文件中,它就没有用了。

【讨论】:

  • 我一直听说对于“基本”函数(例如“get”获取内部变量)它可以提高速度和内存?
  • @paul23:在大多数现代环境中,编译器会考虑内联任何函数 - 无论是否标记为 inline - 并生成链接时间代码,即使它们是在不同的源文件中定义的。 inline 只允许您将这些函数放置在(历史上)编译器更容易内联的位置,即头文件。它不保证哪些调用实际上是内联的。
  • 我还是不明白。其他 Stackoverflow 答案清楚地表明声明应该在头文件中完成,并且类方法实现应该在 inline 关键字之前,就像 OP 在这里所做的那样。示例 - stackoverflow.com/a/953731/1469954。那为什么会失败呢?你能把翻译单元的事情说清楚一点吗?
  • 我使用VS2017的重构功能将函数从.h移动到.cpp文件。 VS2017 自己添加了“inline”关键字。让我感到困惑的是,只有带参数的函数才会让链接器抱怨 LNK2019。像 a(void) 这样的函数已经链接好了。如您所述,手动删除“内联”解决了问题。
【解决方案2】:

在实施中有些不一致。 如果此代码是在类定义中编写的,则不需要“Object::”。有时这可能会导致编译器错误。只需擦除它并重试。 如果是写出类定义,这里不能声明inline。

【讨论】:

    【解决方案3】:

    代码中的构造函数名称中有一个小写的o,无论是否内联。 C++ 名称区分大小写。

    试试这个:

    inline Object::Object(double x) : _x(x) {}
    

    我不清楚您发布的代码中的 /* lots more */ 评论是什么意思。如果此声明中有其他参数,则构造函数的定义必须与之匹配。

    【讨论】:

    • 糟糕,发帖时打错了。 检查 - 是的。
    • @paul23。请发布当前失败的确切代码,以及与该代码匹配的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    相关资源
    最近更新 更多