为什么我不能在另一个文件中定义内联成员函数?

11

我有三个文件:

1. Joy.h

class Joy
{
public:
    void test();
};

2. Joy.cpp

#include "Joy.h"
inline void Joy::test() {}

3. main.cpp

#include "Joy.h"    
int main()
{
    Joy r;        
    r.test();        
    return 0;
}

我尝试使用以下命令编译它们:

g++ cpp Joy.cpp
main.cpp:(.text+0x10): undefined reference to `Joy::test()'

有谁能告诉我为什么……

如果我不想在.h文件中定义test()函数但仍希望它成为一个inline函数,该如何解决这个问题?


1
你应该把 inline 函数放在头文件中。你可能也会对链接时优化(g++ -flto 使用最新的 GCC 版本) 感兴趣。 - Basile Starynkevitch
@kev,哦,抱歉~~我在这里是新手,对C++也是初学者,谢谢。 - Yishu Fang
5个回答

12

定义内联成员函数时,应在成员函数的定义前面加上关键字inline,然后将该定义放入头文件中。

声明函数为内联函数基本上是告诉编译器(如果可能),在调用函数的地方用函数的内容替换调用函数的代码。这样做的想法是,函数体可能很小,而调用函数所需的开销比函数体本身还要大。

为了能够这样做,编译器需要在编译调用函数的代码时看到该函数的定义。这意味着该定义必须驻留在头文件中,因为调用函数的代码只能访问头文件。

参考阅读:
[9.7] 如何告诉编译器将成员函数设置为内联函数?


当我访问该网站时,出现“您没有权限访问此服务器上请求的文件”的错误。你能否通过其他链接帮助我解决这个问题? - Rakholiya Jenish

4
编译器需要完整的函数定义,以便在调用它的地方进行内联。只有在头文件中定义才能实现这一点。
inline函数如何工作?
假设你定义了这个函数:
 inline void increment(int &i) { ++i; }

然后将其用作:

int i = 0;
while( i < N )
{
    std::cout << i << std::endl;
    increment(i);
}

然后编译器会将这段代码翻译成以下形式(简单来说):
int i = 0;
while( i < N )
{
    std::cout << i << std::endl;
    ++i; //replaced the call with the equivalent code which the function 
         //actually executes to produce the same effect
         //(edit typo) it replaces to ++i and not i++ as it was the original.
}

将函数调用替换为函数本身的代码被称为内联。你可以说,该函数已被内联。

请注意,inline关键字只是编译器的提示:它告诉编译器尽可能地内联我。并不保证每个inline函数调用都会被编译器内联


4

标准是ISO/IEC 14882:2011。措辞应为“...在其中它被_odr-used_...”,但除此之外:+1。 - CB Bailey
@Charles 你说得对。我引用的是最后一个工作草案(我认为是最后一个),日期为2011年2月28日。 - Bojan Komazec
@CharlesBailey:你能告诉我从哪里获取C++11(ISO/IEC 14882:2011)标准吗?谢谢~~ - Yishu Fang
@UniMouS:请访问http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50372,并查看此处链接:https://dev59.com/wnVD5IYBdhLWcg3wHnyd,了解更多相关编程信息。 - CB Bailey

1
由于C++编译成独立的编译单元(通常是每个cpp文件),一个cpp文件的编译不知道另一个编译单元中内联函数的实现,因此无法进行内联。
解决方案是将内联函数的实现放在头文件中,这样使用该头文件的所有文件都可以访问实现。

0
一个内联函数是编译器被要求执行内联扩展的函数。
因此,内联函数的整个重点在于它是在代码中实现的。如果您仍希望它成为内联函数,则没有任何其他定义方式。inline function

更确切地说,它可以在调用函数内联,而且当编译该函数时,该函数只能访问头文件。 - Damien_The_Unbeliever

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