我想要包含在另一个cpp文件中的头文件。我想知道如果我写这样的头文件有什么区别,
#include <iostream>
#include <string>
using namespace std;
string ret()
{
return "called";
}
===================================
#include <iostream>
#include <string>
using namespace std;
static string ret()
{
return "called";
}
无论如何我都可以访问ret()
功能!那么,静态的用途是什么?
答案 0 :(得分:5)
这是一个非常邪恶的头文件,你正在展示。
从不将using namespace std;
放入头文件中。这会强制包括标头在内的任何人在全局命名空间中拥有所有std
。
使用某种形式的包含警卫。
static
使该函数在包含它的.cpp
之外不可见。这意味着包含标题的每个.cpp
都有自己的函数副本。只有在您特别需要此行为时,才应使用static
(非成员)函数。
如果不使用static
,则应将定义从标题移动到源文件中(如果要将其定义一次),或者声明函数inline
(如果可能的话,它的代码将在每个呼叫站点上内联。如果不同时执行这些操作,如果将标题包含在多个源文件中,则会出现多个定义错误。
答案 1 :(得分:4)
第一个头文件定义了一个名为ret
的函数,在包含它的每个翻译单元中都有外部链接。如果在同一程序中链接了多个此类TU,则这是不正确的。
第二个头文件定义了一个名为ret
的函数,在包含它的每个翻译单元中都有内部链接。这意味着每个TU都有自己的函数私有副本(具有不同的地址),无论有多少链接在一起。
使用头文件共享代码有三种正确的方法:
static
替换为inline
)。 inline
的含义是虽然程序中只有一个函数副本,但每个使用该函数的TU都包含它的定义。在C ++ 03中有第四种方式:
我相信这在C ++ 11中仍然可用,但在C ++ 11中,无名空间中的函数默认具有内部链接。我不知道在C ++ 11中使用无名空间中的函数有任何外部链接。因此,就函数而言,无名空间是提供函数内部链接的好方法。
您使用哪一个取决于您的需求。第三个选项意味着你可以在不重新编译调用代码的情况下更改函数的定义,尽管除非函数在dll中,否则你仍然需要重新链接可执行文件。
前两个(static
或inline
)在以下情况下的行为不同:
static
局部变量ret
进行比较,否则它们大致相同。
根据标准,inline
也提示编译器应优化对该函数的调用以便快速执行(实际上,这意味着内联调用站点的代码)。大多数编译器大多数时候都忽略了这个提示。如果他们认为它是一个很好的内联候选者,他们会愉快地内联static
但非inline
函数,如果他们评估它是inline
函数,他们会很乐意避免内联的不良候选人。
答案 2 :(得分:2)
使用标题保护。
不要在头文件中使用“using namespace”。 (实际上,不要在头文件中使用“using”。使用完全限定的标识符。)
使用声明函数的标头,而不是定义它们。您希望ret()
的代码仅出现在生成的可执行文件中一次。您可以通过将ret()
的定义(代码)放在.cpp文件中来实现此目的。 一个 .cpp文件,而不是多个(通过包含定义)。
头文件列出函数ret()
的声明,以便其他代码“知道”该函数存在,它采用哪个参数以及它返回的内容。
答案 3 :(得分:1)
如果在头文件中将c ++方法定义为static
,则每个转换单元(包含该头文件的每个.cpp文件)将具有这些静态方法的不同版本 - 它们将不具有相同的地址空间。
因此,程序的大小会不必要地增加。
另外,为了清楚起见:
仅在.cpp文件中将方法定义为static
意味着该方法具有静态链接,并且只能从同一.cpp文件中的其他方法访问。