我正在使用Visual Studio 2012完成《编程原理与实践》中的练习。当试图编译下面的源代码时,我得到了一个链接器错误:
未解析的符号int foo。
我不明白为什么这个符号没有解决。
我的.h
extern int foo;
void print_foo();
void print(int);
my.cpp
#include "my.h"
#include "../../std_lib_facilities.h"
void print_foo()
{
cout<<foo<<'n';
}
void print(int i)
{
cout<<i<<'n';
}
使用.cpp
#include "my.h"
int main(){
int foo = 7;
print_foo();
print(99);
}
extern int foo;
这是一个声明。它告诉编译器"在某个地方定义的全局名称空间中将有一个int
类型的foo
变量"。
int main(){
int foo = 7;
// ...
}
这在函数main()
中定义了int
类型的局部变量foo
,并将其初始化为7。此局部变量在main()
之外不可见。
实际上,您没有在全局命名空间中定义foo
。要做到这一点,请将此行添加到中,正好是my.cpp
或use.cpp
中的一个,位于include:之后
int foo;
这在全局命名空间中定义了一个类型为int
的名为foo
的变量。(作为静态存储持续时间的对象,foo
默认初始化为零,但如果需要,也可以提供不同的初始化器。(然后,当您将对象文件链接在一起时,链接器应该能够解析对print_foo()
中全局foo
的引用。
非常重要的是,您只能定义foo
一次,尽管您可以声明任意多次。否则会违反一个定义规则,如果幸运的话会导致链接器错误,如果不幸运的话则会导致未定义的行为。
此语句
extern int foo;
是名称foo的声明。这不是foo的定义。
你必须初始化这个变量,它才会成为一个定义。例如
extern int foo = 0;
尽管我看不出你的代码有什么意义。
也许你的意思是。我假设变量是在模块中定义的,因为如果只有一个模块,我看不到使用头的意义。
/* my.cpp */
#include "../../std_lib_facilities.h"
extern int foo = 0;
void print_foo();
void print(int);
void print_foo()
{
cout<<foo<<'n';
}
void print(int i)
{
cout<<i<<'n';
}
int main(){
extern int foo;
foo = 7;
//...
如果你想使用标题,那么代码可以看起来像
/* my.h */
extern int foo;
void print_foo();
void print(int);
/* my.cpp */
#include "my.h"
#include "../../std_lib_facilities.h"
int foo;
void print_foo()
{
cout<<foo<<'n';
}
void print(int i)
{
cout<<i<<'n';
}
/* use.cpp */
#include "my.h"
int main(){
extern int foo;
foo = 7;
print_foo();
print(99);
}