4

我对 .cpp 文件之间的变量访问如何工作有点模糊。例如:

主文件

int main()
{
    int a = i;
    return 0;
}

main2.cpp

int i;

这会在 main.cpp 上生成一个编译器错误,告诉我 i 中不存在。那么,“静态”关键字在这种情况下有什么区别呢?(我试过用谷歌搜索,但大多数“静态关键字”信息页面都在谈论类和函数)

main2.cpp

static int i;

是一样的吗?它是否防止extern int i被用于访问i其他地方?匿名命名空间的使用在处理变量方面有何不同?

main2.cpp

namespace
{
    int i;
}

总结一下:

  • .cpp 文件之间可以访问变量吗?(除了 extern 关键字)
  • 全局变量上的 static 关键字如何影响事物?
  • 匿名命名空间如何以不同的方式影响事物?
4

3 回答 3

3

在您的第一个示例中,main2.cpp定义了一个全局变量i,如果该文件中出现了 的声明,则可以访问该变量。(通常,extern 声明来自头文件。)您收到编译器错误,因为从未在 中声明,这意味着编译器假定没有这样的变量。main.cppexterniimain.cpp

在您的第二个示例中,main2.cpp定义了一个文件范围变量i。文件范围变量与全局变量不同,即使它们碰巧同名。如果您在第二个示例中有一个iin的 extern 声明main.cpp,那么这两个文件都会成功编译,但是您会得到一个链接错误,因为没有定义全局变量i

如果您main2.cpp将第二个示例重命名为 to ,添加tomain3.cpp的 extern 声明,编译所有三个并将它们链接在一起,那将成功;main.cpp 和 main2.cpp 将共享一个名为 的变量,并且将拥有自己完全独立的变量,也名为。imain.cppimain3.cppi

这东西叫做联动。命名空间几乎与链接完全无关。但是,匿名命名空间是特殊的。在匿名命名空间中定义一个变量与定义它的所有实际目的相同static——它使它成为一个文件范围变量。(如果我没记错的话,是有区别的,但只有当你用导出的模板做复杂的事情时才重要,而且导出的模板很少使用,以至于他们正在谈论从 C++ 标准中删除该功能,你不需要'不必担心。)

匿名命名空间的价值在于您可以在其中放置一个类定义,这使得该类的所有方法都是文件本地的。(只有class { ... }块必须在namespace { ... }块内才能获得此效果。)您不能以任何其他方式做到这一点。

于 2010-09-07T19:59:32.853 回答
1

所有全局变量都有某种联系extern需要链接才能在不同文件之间的不同上下文中命名相同的变量。

extern是默认值。如果您实际extern在变量声明中使用,它会被视为对另一个文件的引用。省略任何链接说明符以实际创建变量;这必须只发生在一个文件中。

extern int i; // i exists somewhere in some .cpp file.
int i; // ah! this is the file it exists in. 
       // (Although nothing special about that.)

static应用于全局(在命名空间范围内)使其成为文件的本地。您可以从私有命名空间获得相同的效果,因此static不推荐使用外部函数或类范围。很多人仍然使用它。

static文件本地意义规则的例外是在类和inline函数中。static应该更恰当地调用类成员,extern因为语义是相同的。这很丑陋且令人困惑,但我猜 Bjarne 只是想消除extern作为关键字。

内联函数可以在多个.cpp文件之间具有相同的定义,因此当一个static变量创建时,变量定义也是共享的。

于 2010-09-07T19:50:16.313 回答
0
  • 是的,例如你可以使用静态类变量
  • 它使变量本地化并持久化到编译单元
  • 匿名命名空间防止符号之间的冲突。就好像您手动创建唯一命名的命名空间
于 2010-09-07T19:51:29.770 回答