从cpp文件内联函数时出现链接错误

5

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

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

它有一个构造函数:explicit Object(double x, /* 其他 */);

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

这个很奏效... 但是如果我在“object.cpp”文件中添加关键字“inline”:

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

突然出现了一个链接器错误!“error LNK2019:未解析的外部符号”

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

编辑:实际上,我注意到对于所有方法都是如此。但是,如果我将所有方法移到object.h头文件中,它确实有效。您无法从定义对象的头文件之外的位置内联函数吗?

编辑2:好的,进行了一次大更新,我决定建立一个快速测试案例:
main.cpp

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

a.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 : error LNK2019: 无法解析的外部符号 "public: void __thiscall a::test(int)" (?test@a@@QAEXH@Z),该符号在函数 _main 中被引用

移除 "inline" 关键字使程序正常工作。将 "a.h" 和 "a.cpp" 合并为一个文件也可以。
我真的想不出还有什么更多的信息要提供了 :/

看一下这个关于内联类成员函数的讨论,它可能会帮助你理解为什么一个或另一个情况会失败。http://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx - Steve Townsend
我认为 inline 不是你所想的意思。你能说一下你想用它实现什么吗? - CB Bailey
3个回答

4
您需要了解有关标记为inline的函数定义规则。
将函数标记为inline意味着您可以在程序中的多个翻译单元中定义该函数(但每个翻译单元仅限一次),但所有定义必须相同,并且您必须在使用该函数的每个翻译单元中提供定义。
在您的示例中,来自main.cpp的翻译单元使用a::test(int),但在该翻译单元中没有定义。在来自a.cpp的翻译单元中定义了一个inline,这意味着您不能在main.cpp的翻译单元中省略定义。
我不确定为什么您想在a.cpp的定义中添加inline,因为这是不必要的或无用的。 inline允许您将函数定义放置在共享头文件中,但如果您想将函数放置在源文件中,则没有用处。

我一直听说对于“基本”功能(例如“get”以获取内部变量),它可以提高速度和内存? - paul23
@paul23:在大多数现代环境中,编译器将考虑内联任何函数 - 无论是否标记为“inline” - 并且使用链接时代码生成,即使它们定义在不同的源文件中。 inline 只是允许您将这些函数放置在编译器更容易内联的位置,即头文件中(从历史上看)。它并不保证哪些调用实际上被内联。 - CB Bailey
我还是不明白。其他Stackoverflow答案明确建议在头文件中进行声明,并且类方法实现应该在前面加上inline关键字,就像OP在这里做的一样。例如-https://dev59.com/PnNA5IYBdhLWcg3wdtld#953731。那么为什么会失败呢?你能否更清楚地解释一下翻译单元的事情? - SexyBeast
我使用VS2017的重构功能将函数从.h文件移动到.cpp文件中。VS2017自动添加了“inline”关键字。 令我困惑的是,只有带参数的函数才会导致链接器报告LNK2019错误。像a(void)这样的函数可以正常链接。 按照您所描述的方法手动删除“inline”即可解决问题。 - Mike

2

您的代码中构造函数名称中有小写字母o,无论是内联还是不内联。C++中名称区分大小写。

请尝试以下更改:

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

我不清楚你在发布的代码中 /* lots more */ 注释的含义。如果在这个声明中有其他参数,那么构造函数的定义必须与之匹配。


糟糕,发帖时打错了一个字。检查一下 - 是的,确实是这样。 - paul23
1
@paul23,请发布当前失败的确切代码和与该代码匹配的错误信息。 - Steve Townsend

0

在实现中有些不协调的地方。 如果这段代码是写在类定义内部的,那么你就不需要"Object::"。有时候这会导致编译错误。只需将其删除并重试即可。 如果是写在类定义外部,你就不能在此处声明为inline。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接