[英]putting function definitions in header files
如果要将函数定义放在头文件中,则似乎有三种不同的解决方案:
inline
static
(直到最近,我甚至还没有意识到#1。)那么这些解决方案有什么区别?何时应该选择哪种解决方案? 我处于仅标头的世界,因此我确实需要标头文件中的定义。
static
和未命名的命名空间版本最终是相同的:每个转换单元将包含它自己的函数版本,这意味着给定静态函数f
,指针&f
在每个转换单元中将不同,并且程序将包含N个不同版本的f
(二进制文件中包含更多代码)。
这并不是提供在头部中的功能的正确的方法,它将提供N个不同的(完全相等)的功能。 如果函数包含static
当地人则会有N个不同的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
ops变量a
对于源文件dk1.cpp
和dk.cpp
是不同的
您可以考虑将方法包装在类而不是名称空间中。 将这些方法声明为static,并删除该类的构造函数,以强调这不是要实例化的对象。
struct FooNamespace
{
FooNamespace() = delete;
static FooMethod1() {
...
}
static FooMethod2() {
...
}
};
您得到的一般行为与仅属于单个实现的属于命名空间的行为相同。
static
函数(等效于匿名名称空间)为每个TU接收不同的副本。 如果函数是可重入的,则它基本上是相同的(某些编译器可能具有汇编级的差异),但如果不是,则每个TU的静态数据都将不同。 内联函数是折叠式的-也就是说,每个TU只有一个静态数据副本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.