extern 内联函数被引用但未定义

Pat*_*ykB 2 c c++ inline extern

void foo(void) {}我有一个我希望内联的函数(让我们称之为它)。但是我在 .cpp 文件中定义了它。
我无法将该函数移动到标头,因为它正在使用 .cpp 中的其他函数。



编辑:
下面的代码就像真实的代码一样不使用 C++ 功能。我可以明确补充:

#ifdef __cplusplus
extern "C"
#endif
Run Code Online (Sandbox Code Playgroud)

如果我想将下面的代码转换为 c99,我只需要更改我的项目属性(或 makefile,如果您愿意)而不是代码。我也在询问c++,因为它可以解决我的问题,而c99不能。
因此我的问题中的 C 和 C++ 标签是合理的。代码是可移植的,
请参阅:When to use extern "C" in C++?



编辑#2
好吧,我明白我必须将foo()定义放在头文件中。如何在不将它们移动到头文件的情况下调用func_a()func_b()from ?foo()有什么解决方法吗?



示例
文件.c/.cpp:

int    func_a (int a,    int b,    int c)    {/*...*/};
double func_b (double a, double b, double c) {/*...*/};

void   foo    (int a, double b) { // unction definition
    //...
    int myInt = func_a(a, 2, 3);
    //...
    double myDouble = func_b(1.5f, b, 3.5f);
    //...
}
Run Code Online (Sandbox Code Playgroud)

文件.h:

// Something before.

void foo (int a, double b); // function declaration

// Something after.
Run Code Online (Sandbox Code Playgroud)



我想指出的是:

  • 我正在使用 Visual Studio 2015。
  • 我正在编写相对较大的项目(〜7000行代码)。它是物理系统的模拟。
  • file.h包含在许多其他编译单元中。
  • foo(int, double)很小,它调用其他函数file.cpp
  • 由于优化原因,我想进行foo(int, double)内联(我最终会使用__forceinline__
  • foo()在我的计划中多次打电话。它还在几个 while 循环中使用(每个循环 100k + 迭代),因此让这个符号foo()不内联是可扩展的。
  • 我厌倦了只有标头的库。



我尝试:
file.c / .cpp:

extern inline
void   foo    (int a, double b) {\*...*\}; // Definition
Run Code Online (Sandbox Code Playgroud)

文件.h:

extern inline
void   foo    (int a, double b); // Declaration
Run Code Online (Sandbox Code Playgroud)

但我不断收到警告:

warning : extern inline function "foo" was referenced but not defined
Run Code Online (Sandbox Code Playgroud)

我不明白为什么我会收到这个警告。



有什么办法可以:

  • foo()保留我的 .cpp 文件中的定义吗?但仍然使其内联
  • 移动foo()file.h,保留func_a()func_b()内部 file.cpp,但使func_a()func_b()符号对foo()(!并且仅对foo()!) “可见”file.cpp
  • 还有其他解决方法吗?


抱歉,我仍在学习 cpp,我不知道我的问题是否清楚,或者是否有可能从 .cpp 文件中内联函数。

Rei*_*ica 5

在 C++ 中,inline关键字的含义是:

  • 该函数的主体必须存在于使用该函数的每个源文件中。
  • 所有源文件中的函数“主体”必须逐个令牌和逐个实体相同。
  • 编译器和链接器必须确保它们适合具有这些“多个主体”的函数

这就是它所做的一切。实际上,这意味着它允许并强制您将函数体放入头文件中。

关键字本身与函数内联无关。只是如果编译器希望能够内联函数体,那么它必须在编译调用代码时能够访问它;换句话说,函数的主体必须位于同一源文件中或位于该源文件包含的头文件中。

如果您想让编译器在所有调用点中内联该函数,并且这些调用点发生在多个源文件中,则必须将该函数放入头文件中(并将其标记为inline)。

另一方面,链接器也可以进行内联,称为链接时代码生成或整个程序优化或类似的东西(取决于工具链的供应商)。启用此功能将

  1. 延长您的构建时间,并且
  2. 允许链接器将函数内联到源文件中的调用站点中

因此,要内联该函数,您有两种选择。要么将该函数放入头文件中,要么启用并依赖链接时优化来为您内联它。


在您的特定情况下,要使用__forceinline__,您需要foo在头文件中进行定义。这需要 的定义foo才能查看func_a和的声明func_b。为了防止名称空间污染,您可以在以下范围内声明这些函数foo

inline void foo(int a, double b) { // function definition
    int func_a(int, int, int);
    double func_b(double, double, double);

    //...
    int myInt = func_a(a, 2, 3);
    //...
    double myDouble = func_b(1.5f, b, 3.5f);
    //...
}
Run Code Online (Sandbox Code Playgroud)