函数原型和声明的可见性
在 C++中,必须在使用前声明或定义代码。例如,以下内容产生编译时错误:
int main()
{
foo(2); // error: foo is called, but has not yet been declared
}
void foo(int x) // this later definition is not known in main
{
}
有两种方法可以解决这个问题:在 main()
中使用 foo()
之前定义或声明 foo()
。这是一个例子:
void foo(int x) {} //Declare the foo function and body first
int main()
{
foo(2); // OK: foo is completely defined beforehand, so it can be called here.
}
但是,也可以通过在使用之前仅放置原型声明来转发声明该函数,然后再定义函数体:
void foo(int); // Prototype declaration of foo, seen by main
// Must specify return type, name, and argument list types
int main()
{
foo(2); // OK: foo is known, called even though its body is not yet defined
}
void foo(int x) //Must match the prototype
{
// Define body of foo here
}
原型必须指定返回类型(void
),函数名称(foo
)和参数列表变量类型(int
),但不需要参数的名称 。
将其集成到源文件组织中的一种常用方法是创建包含所有原型声明的头文件:
// foo.h
void foo(int); // prototype declaration
然后在别处提供完整的定义:
// foo.cpp --> foo.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
void foo(int x) { } // foo's body definition
然后,一旦编译,将相应的目标文件 foo.o
链接到编译目标文件中,在链接阶段使用它,main.o
:
// main.cpp --> main.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
int main() { foo(2); } // foo is valid to call because its prototype declaration was beforehand.
// the prototype and body definitions of foo are linked through the object files
当函数原型和调用存在时,会发生未解析的外部符号错误,但未定义函数体。由于编译器在最后的链接阶段之前不会报告错误,并且它不知道在代码中跳转到哪一行来显示错误,因此解决这些问题会更加棘手。