这个问题是关于普通的c函数,而不是c++的静态方法,在评论中已经澄清了。
我知道什么是静态变量,但是什么是静态函数呢?
为什么如果我声明一个函数,让我们说void print_matrix,在让我们说a.c(没有a.h),并包括“a.c”-我得到“print_matrix@@....)已经定义在a.b obj”,但如果我声明它为静态void print_matrix,然后它编译?
只是澄清一下——我知道包含。c是不好的,就像你们很多人指出的那样。我这样做只是为了暂时清除main.c中的空间,直到我更好地了解如何将所有这些函数分组到适当的.h和.c文件中。只是一个临时的,快速的解决方案。
因为静态函数只在这个文件中可见。
实际上,编译器可以为你做一些优化,如果你声明“静态”的一些函数。
这里有一个简单的例子。
c
#include <stdio.h>
static void test()
{
ghost(); // This is an unexist function.
}
int main()
{
int ret = 0;
#ifdef TEST
#else
test();
#endif
return (ret);
}
并使用
gcc -o main main.c
你会看到它失败了。因为你甚至没有实现ghost()函数。
但是如果我们使用下面的命令。
gcc -DTEST -O2 -o main main.c
测试成功,程序可以正常运行。
为什么?这里有3个关键点。
-O2:编译器优化级别至少2。
-DTEST:定义TEST,因此TEST()将不会被调用。
为test()定义了“static”。
只有这3个条件都为真,才能通过编译。
由于这个“静态”声明,编译器可以确认test()将永远不会在其他文件中被调用。编译器可以在编译时删除test()。因为我们不需要test(),所以是否定义或实现ghost()并不重要。
首先:在另一个文件中包含.cpp文件通常是一个坏主意——它会导致这样的问题:-)正常的方法是创建单独的编译单元,并为所包含的文件添加一个头文件。
其次:
c++在这里有一些令人困惑的术语——直到在评论中指出,我才知道它。
a)静态函数——继承自C语言,以及你在这里谈论的东西。在任何课堂之外。静态函数意味着它在当前编译单元之外是不可见的——所以在你的例子中,a.b obj有一个副本,而你的其他代码有一个独立的副本。(在最终的可执行文件中添加多个代码副本)。
b)静态成员函数——面向对象定义的静态方法。存在于类中。您可以使用类而不是通过对象实例调用它。
这两种不同的静态函数定义是完全不同的。小心点——这里有龙。
C中的静态函数和c++中的静态成员函数之间有很大的区别。在C语言中,静态函数在其翻译单元(即它被编译到的目标文件)之外是不可见的。换句话说,使函数静态限制了它的作用域。您可以将静态函数视为其*.c文件的“私有”(尽管严格来说这并不正确)。
在c++中,“static”也可以应用于类的成员函数和数据成员。静态数据成员也称为“类变量”,而非静态数据成员则称为“实例变量”。这是Smalltalk术语。这意味着类的所有对象共享的静态数据成员只有一个副本,而每个对象都有自己的非静态数据成员副本。静态数据成员本质上是一个全局变量,它是类的成员。
非静态成员函数可以访问类的所有数据成员:静态和非静态。静态成员函数只能对静态数据成员进行操作。
考虑这个问题的一种方法是,在c++中,静态数据成员和静态成员函数不属于任何对象,而是属于整个类。
小提示:静态函数对于翻译单元是可见的,在大多数实际情况下,翻译单元是定义函数的文件。您所得到的错误通常被称为违反了一个定义规则。
标准可能是这样说的:
“每个程序都应该包含一个非内联的定义
程序中使用的函数或对象;没有诊断
必需的。”
这是C语言看待静态函数的方式。然而,这在c++中是不推荐的。
此外,在c++中,可以将成员函数声明为静态。这些主要是元函数,即它们不描述/修改特定对象的行为/状态,而是作用于整个类本身。此外,这意味着您不需要创建对象来调用静态成员函数。此外,这也意味着您只能从这样的函数中访问静态成员变量。
我要在Parrot的例子中添加Singleton模式,它基于这种静态成员函数,在程序的整个生命周期中获取/使用单个对象。