C++函数原型

4

我刚开始学习C++,有人可以解释一下以下C++函数原型的区别吗?

void f(int n);
extern void f(int n);
static void f(int n);
5个回答

11
void 和 extern void 版本是相同的。它们表示函数具有外部链接性(即,函数的定义可能来自于某个其他的C或C++文件)。Static 表示函数具有内部链接性,并且仅存在于当前的C++文件中。
你几乎从不会看到这些限定词应用于函数,因为99.9%的情况下,你希望使用默认的 extern 行为。
你可能会在全局变量上看到 static 或 extern 存储限定符,这通常是为了降低与同一项目中的其他文件的名称冲突。这是从 C 中传统继承而来的;如果你正在使用 C ++,则应该使用匿名命名空间而不是 static 来完成这种事情。

4
轻微的挑剔:第一个并不一定表示外部链接。它可能只是一个前向声明,用于将稍后在同一翻译单元中出现的函数定义与之关联。 - Charles Salvia
@Charles:如果函数存在于同一实现文件中,则它将由该文件导出供其他文件使用,在这种情况下,它仍具有外部链接性。(尽管,您正确指出该函数本身不需要来自另一个翻译单元) - Billy ONeal
对,我应该表述为“并不一定意味着函数定义应该在其他C或C++文件中”。 - Charles Salvia
@Charles:稍作修改。更好了吗? - Billy ONeal
@Neil G:我很困惑。我确实提到了匿名命名空间。 - Billy ONeal

4

这更多是关于C语言的问题而非C++,但是:

void f(int n);

声明一个函数f,该函数接受一个整数参数。
extern void f(int n);

声明了一个函数f,它接受一个整型参数,但存在于其他文件中。编译器会相信你已经在某个地方实现了该函数。如果链接器找不到它,你将获得一个链接器错误。

static void f(int n);

声明一个函数f,它接受一个整数参数。static关键字使其变得有趣。如果它在.cpp文件中,该函数只对该文件可见。如果它在.h文件中,每个包含该头文件的.cpp文件将创建自己的该函数副本,仅可访问该实现文件。


3
第一种和第二种是相同的。第三个会给f内部联接,这意味着不同的源文件可以使用名字f来表示不同的东西。
不应该使用第三个例子中的static。而应该使用一个匿名命名空间:
namespace { // anonymous
  void f(int n);
}

0
到目前为止,两个答案都已经弃用了静态函数的使用。为什么?是什么使得
命名空间 {
void f(int n);
}

static void f(int n);
更好呢?它不是更简单,更容易理解...

1
我认为匿名命名空间是指示内部链接更好的解决方案。static关键字已经足够重载了。 - Charles Salvia
@Charles:严格来说,匿名命名空间中的函数仍具有外部链接: http://bytes.com/topic/c/answers/835990-anonymous-namespace-linkage - Nemanja Trifunovic
@Nemanja:但这实际上没有关系;即使符号被导出,它也是静态的,因为它由一个真正的命名空间支持,该命名空间被赋予一个生成的名称。您无法从其他文件调用它,因此它可能与静态相同。 - Billy ONeal
@Billy:你说得基本正确。唯一的区别是外部链接会影响链接速度,在足够大的项目上会变得明显。 - Nemanja Trifunovic

0

匿名命名空间是一种更通用和更清洁的解决方案,您可以在其中拥有函数、变量和类。而static则是一个过于重载的术语,在某些情况下意味着内部链接,在其他情况下则意味着静态生命周期。
然而,匿名命名空间有一个缺点。由于外部链接,您的对象/库文件的导出部分将膨胀,并包含所有这些长长的<unique namespace name>::<function>名称,如果它们是静态的,则不会存在这些名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接