在C/C++中,函数定义是放在头文件中还是只有声明?
以
math.h
中的pow()
函数为例。如果函数的定义不在头文件中,那么头文件中包含什么内容才能正确链接函数定义呢?math.h
中的pow()
函数为例。如果函数的定义不在头文件中,那么头文件中包含什么内容才能正确链接函数定义呢?// <cmath>
namespace std {
double pow(double base, double exp);
}
#include <cmath>
double std::pow(double base, double exp) {
// Do stuff...
}
不同之处在于定义的函数具有代码块(用花括号{...}
表示)。因此,声明和定义的区别在于定义包含了函数的底层代码,而声明则没有任何代码。
但是假设只是声明,编译器如何知道函数的位置呢?
通常情况下,C++被编译为不同的“翻译单元”(即文件)。每个翻译单元都包括一个公共头文件(这里是<cmath>
),该头文件提供了其函数的声明(这里是::std::pow
)。
其中一个单元还包含::std::pow
的定义。当这些单元(以目标文件或库的形式)由链接器放在一起时,对函数的所有使用都将调用在定义它的单元中的适当代码。如果未链接定义函数的单元,则链接器将报错。
::std::pow
的定义,链接器会因为多个定义而报错。inline
存储类说明符指定),可以在多个单元中定义,但最终只保留一个定义。这也包括constexpr和consteval(立即)函数,它们都隐式地是内联函数。static
存储类说明符指定),它们是局部于其所在的翻译单元的;即使它们具有相同的标识符,也不会与其他单元中的符号冲突。::std::pow
的情况实际上相当复杂。通常情况下,它会被外部定义。然而,从C++26开始,它必须是一个constexpr函数,所有这些函数都是内联的根据定义(参见cppreference)。::std::exit
),但也有许多函数在其各自的头文件中定义(例如::std::is_constant_evaluated
)。在其他情况下,外部函数在后续的标准版本中变成了内联函数(就像::std::pow
的情况一样)。
::std::pow
可能在 <cmath>
头文件中定义... 也可能不是。这取决于实现和标准的版本。
static inline
函数是有意义的。 - Jonathan Lefflerstatic inline
函数是有意义的。 - Jonathan Lefflerstatic inline
函数是有意义的。 - undefined