如果要将函数定义放在头文件中,则会出现三种不同的解决方案:
- 将功能标记为
inline
- 将功能标记为
static
- 将该函数放在匿名命名空间中
(直到最近,我甚至都没有意识到#1。)那么这些解决方案有什么不同之处,何时我应该选择哪种?我是在仅限标题的世界中,所以我真的需要头文件中的定义。
如果要将函数定义放在头文件中,则会出现三种不同的解决方案:
inline
static
(直到最近,我甚至都没有意识到#1。)那么这些解决方案有什么不同之处,何时我应该选择哪种?我是在仅限标题的世界中,所以我真的需要头文件中的定义。
该 static
和未命名的命名空间版本最终是相同的:每个翻译单元将包含它自己的函数版本,这意味着给定一个静态函数 f
,指针 &f
每个翻译单元会有所不同,程序将包含N个不同版本的 f
(二进制代码中的更多代码)。
这是 不 提供正确的方法 一个 函数在标题中,它将提供 ñ 不同(完全相同)的功能。如果函数包含 static
然后当地人会有 ñ 不同 static
局部变量......
编辑:为了使它更明确:如果你想要的是在不破坏一个定义规则的情况下在头中提供函数的定义,正确的方法是使函数成为函数 inline
。
据我所知,只有 inline
和模板函数可以在头文件中定义。
static
不推荐使用函数,而应使用未命名的命名空间中定义的函数(参见7.3.1.1 p2)。当您在标头中的未命名命名空间中定义函数时,包含该标头(直接或间接)的每个源代码都将具有唯一的定义(请参阅7.3.1.1 p1)。因此,不应在头文件中的未命名命名空间中定义函数(仅在源文件中)。
引用的标准来自c ++ 03标准。
编辑:
下一个示例演示了为什么函数和变量不应该在头文件中定义到未命名的命名空间中:
ops.hpp 包含:
#ifndef OPS_HPP
#define OPS_HPP
namespace
{
int a;
}
#endif
dk1.hpp 包含:
#ifndef DK1_HPP
#define DK1_HPP
void setValue();
void printValue();
#endif
dk1.cpp 包含:
#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>
void setValue()
{
a=5;
}
void printValue()
{
std::cout<<a<<std::endl;
}
dk.cpp 包含:
#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>
int main()
{
// set and print a
setValue();
printValue();
// set and print it again
a = 22;
std::cout<<a<<std::endl;
// print it again
printValue();
}
编译如下:
g++ -ansi -pedantic -Wall -Wextra dk.cpp dk1.cpp
和输出:
5
22
5
选择变量 a
与源文件不同 dk1.cpp
和 dk.cpp
static
函数(相当于匿名命名空间)为每个TU接收不同的副本。如果函数是可重入的,则这基本相同(某些编译器可能具有汇编级差异),但如果不是,那么每个TU将具有不同的静态数据。内联函数是折叠的 - 也就是说,它们每个TU只有一个静态数据副本。