内联函数链接错误

33

我试图使用特定类的内联成员函数。例如,没有内联的函数声明和实现如下:

在头文件中:

int GetTplLSize();
在 .cpp 文件中:
int NeedleUSsim::GetTplLSize()
{
    return sampleDim[1];
}

如果我在实现和声明中的任何一个地方,或者两个地方都加入"inline"关键字,就会出现链接器错误,如下所示:

 创建库文件 C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.x 和对象 C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.exp
mexfunction.obj: 错误 LNK2019: 无法解析的外部符号 "public: int __thiscall NeedleUSsim::GetTplLSize(void)" (?GetTplLSize@NeedleUSsim@@QAEHXZ),该符号在函数 _mexFunction 中被引用 
mexfunction.mexw32: 致命错误 LNK1120: 1 个未解析的外部
C:\PROGRA~1\MATLAB\R2008B\BIN\MEX.PL: 错误: 链接 'mexfunction.mexw32' 失败。

为了消除这个错误,需要做什么(也就是说,在使用这些内联成员函数方面做错了什么)?

5个回答

36

你需要把函数定义放在头文件中。让编译器进行内联的最简单方法是在类声明中包含方法体,例如:


class NeedleUSsim
{
  // ...
  int GetTplLSize() const { return sampleDim[1]; }
  // ...
};

或者,如果你坚持分别声明和定义:


class NeedleUSsim
{
  // ...
  int GetTplLSize() const;
  // ...
};

inline int NeedleUSsim::GetTplLSize() const
{ return sampleDim[1]; }

该定义必须在使用该方法的每个翻译单元中可见。


这是唯一的方法吗?(我想为了可读性将声明和实现分开) - stanigator
1
基本上是的。编译器在编译对函数的调用时必须知道函数的主体,因此主体必须在包含的头文件中。 但是,您仍然可以在类声明中仅声明函数,并在稍后的头文件中添加实现。 - Hans
4
有些人喜欢将内联函数放在一个独立的头文件中,并从主头文件(末尾处)包含它,而不是将它们放在主头文件中。我个人并不完全信服它(对我来说感觉有点浪费时间),但如果你喜欢,那就是另一种选择。 - markh44
1
是的,我不想提那个.inl可悲的技术 :) - Nikolai Fetissov
在XCode 4.2中,只有顶部的方法适用于我(没有const因为我试图创建一个setter)。如果我尝试第二个方法,它不起作用。 - Miek
显示剩余2条评论

28

2
不幸的是,正如我刚刚吃了苦头发现的那样,在MSVC 2013和2015中并非如此。我在一个CPP文件(库中)中有一个内联,并且它的代码被从一些完全不同的CPP源代码中调用,该源代码具有自己的内联,名称相同(但代码略有不同,因此结果破坏了测试)。我认为这是该开发环境中的一个错误。很难找到... - chksr

5

正如其他人已经指出的那样,您需要将内联函数的定义移动到头文件中,像这样:

class NeedleUSsim
{
  // ...
  inline int GetTplLSize() { return sampleDim[1]; }
  // ...
};

原因是编译器需要知道在看到内联函数调用时要内联哪些代码。如果您将NeedleUSsim类的函数定义留在.cpp文件中,那么编译器为其生成的代码将被困在NeedleUSsim对象文件中。由于编译器仅读取源代码,它从不窥视另一个类的对象文件,因此它根本无法知道在编译另一个.cpp文件时使用什么代码替换调用。


4
如果您有一个内联函数,应该将定义放在头文件中。

我尝试在头文件中的定义上加上inline关键字,但仍然出现相同的链接器错误。 - stanigator
3
不仅仅是inline关键字,整个定义都应该放在头文件中。因此,请将它从您的.cpp文件移动到您的.h文件中。 - ChrisInEdmonton

0

请参考 内联保护宏语法。这样至少可以将代码与声明略微分开。同时,它还允许您通过define切换函数的内联。


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