为什么在 .cpp 文件中不能内联函数定义?

3

为什么不能在.cpp文件中内联函数或类成员函数定义?例如,在下面的测试示例中,如果我尝试在cpp文件中内联函数或类成员定义,链接器会给我一个未定义引用错误:

test.h

void print();

class A
{
    public:
        void print() const;
};

test.cpp

#include <test.h>

inline void print()
{
    // implementation
}

inline void A::print() const
{
    // implementation
}

main.cpp

#include <test.h>

int main(int argc, char** argv)
{
    print(); // undefined reference to `print()'
    A a;
    a.print(); // undefined reference to `A::print() const'

    return 0;
}

我已经阅读了这里的一些答案,但我仍然不确定它是如何工作的。


可能是因为可以在.cpp文件之间内联函数。如果从函数中删除inline,它们将正常工作甚至可能被内联 - Bo Persson
3个回答

15

Q) 为什么不可能在.cpp文件中内联函数定义?

可以在.cpp文件中内联函数。

但是,您不能从不同的.cpp文件中访问这些inline函数。

内联函数必须存在于每个使用它的文件中。这就是为什么它们经常出现在头文件中,以便需要使用它的任何源文件都包含了包含该文件的头文件。


4
inline 关键字很令人困惑,但对于这个用例来说,如果你知道其含义,它仍然是清晰的。 inline 影响需要生成的代码的要求。更具体地说,它告诉编译器不需要为该函数预见一个函数指针。与常规情况一样,可以将内容复制到调用者中。由于有了 inline,原始函数就不需要被创建。因此,在 test.o 中没有函数指针。
在 main.o 中,您调用此函数。因此,它尝试解析未创建的函数指针,从而导致此链接器错误。
例如,可以使用 clang 的编译器警告来找到这些情况: -Wundefined-inline 编辑 内联函数不会有函数指针吗?并不是这样,完全可以获取此函数的地址并使用和传递它。但是,由于该函数是内联的,因此不能依赖此函数指针与同一函数的另一个地址相等。
在这种情况下,您将在对象文件中的某个位置拥有函数指针。但是,在这种情况下,编译器不需要提供正确的重载名称,以便可以从另一个编译单元中使用它。

那么,无论函数的内容是否被复制,当该函数被内联时,永远不会有指向该函数的函数指针? - Andi
这取决于你的编译器。虽然如此,你不能依赖它。但是,如果你获取地址,会涉及到一些额外的丑陋操作,让我补充一下。 - JVApen
哦,好的。但是即使函数指针可能存在,链接器在这种情况下仍会抱怨? - Andi

2

来自cppreference.com

内联函数或变量(自C++17起)的定义必须存在于访问它的翻译单元中(不一定在访问点之前)。

您的函数被定义在test.cpp中,但是您从main.cpp中访问它们。


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