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

时间:2016-11-23 13:52:25

标签: c++ c inline extern

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



编辑:
下面的代码就像真正的代码一样,不使用c ++功能。我可以清楚地补充一下:

#ifdef __cplusplus
extern "C"
#endif

如果我想将下面的代码转换为c99,我只需要更改我的项目属性(如果你愿意,还可以更改makefile) NOT THE CODE 。我也问c ++因为meaby它可以解决我的问题,而c99不能。
因此我的问题中的C和C ++标签是合理的。代码是便携式的
见:When to use extern "C" in C++?



编辑#2
好的,我明白我必须将foo()定义放在头文件中。如何从func_a()调用func_b()foo()而不将其移至头文件?有没有解决方法?



例子
file.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);
    //...
}

file.h:

// Something before.

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

// Something after.



我想指出:

  • 我正在使用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

file.h:

extern inline
void   foo    (int a, double b); // Declaration

但我一直收到警告:

warning : extern inline function "foo" was referenced but not defined

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



有没有办法:

  • 在我的.cpp文件中保留foo()的定义?但仍然使其内联
  • foo()移至file.h,将func_a()func_b()移至file.cpp内,但制作func_a()func_b()个符号来自foo()
  • foo()(仅限于file.cpp!)“可见”
  • 任何其他解决方法?


Sory我还在学习cpp而且我不知道我的问题是否清楚,或者甚至可以从.cpp文件中内联函数。

1 个答案:

答案 0 :(得分:3)

在C ++中,inline关键字表示:

  • 函数的主体必须出现在使用该功能的每个源文件中。
  • 所有源文件中的函数“body”必须是逐个令牌的,并且逐个实体相同。
  • 编译器和链接器必须确保它们对具有这些“多个主体”的功能很好。

这就是它所做的一切。实际上,这意味着它可以使和强制将函数体放入头文件中。

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

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

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

  1. 延长您的构建时间,
  2. 允许链接器将函数内联到源文件中的调用站点
  3. 所以为了内联函数,你有两个选择。将函数放入头文件,或启用并依赖链接时优化为您内联。

    在您的特定情况下,要使用__forceinline__,您需要在头文件中定义foo。这需要foo的定义才能看到func_afunc_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);
        //...
    }