我有4个文件:
shared.h:
#ifndef SHARED_H
#define SHARED_H
int* sth;
#endif
something.h:
#ifndef SOMETHING_H
#define SOMETHING_H
class foo
{
public:
void printVar();
};
#endif
something.cpp:
#include <iostream>
#include "something.h"
#include "shared.h"
using namespace std;
void foo::printVar()
{
cout<<"Foo: "<<*sth<<endl;
};
main.cpp中:
#include <cstdlib>
#include <iostream>
#include "shared.h"
#include "something.h"
using namespace std;
int main(int argc, char *argv[])
{
sth=new int(32);
foo x;
cout<<"Main: "<<*sth<<endl;
x.printVar();
system("PAUSE");
return EXIT_SUCCESS;
}
编译器返回* sth;
的多重定义我在* sth中添加了静态修饰符并编译,但崩溃了。我更改了打印以打印指针的地址,我已经返回了程序:
Main: 0x3e0f20
Foo: 0
为什么没有分配foo的指针?我想在main中只分配一次,然后在其他文件中共享...我该怎么做?它是extern
修饰符吗?
任何回复的Thanx。
答案 0 :(得分:5)
在shared.h中你想说:
extern int* sth;
承诺编译器存在于某处。
然后在一个(只有一个).cpp文件中你需要写:
int* sth;
使其真正存在。一般来说,您可能想阅读the difference between declaration and definition。根据经验,您只想在头文件中声明事物,而不是定义它们。
当你以前写过static
时,你说每个文件中都存在一个同名的变量,但每个文件都是“本地的”,即main.cpp中的sth
不是与something.cpp中的sth
相同。
答案 1 :(得分:4)
是的,请使用extern
。将extern int* sth;
放入标题中,然后将一个放入int* sth;
的源文件中。
extern
告诉编译器和链接器实际的变量/函数定义在另一个编译单元(即另一个源文件)中。
答案 2 :(得分:2)
您需要在标头中将sth
标记为extern
以使其成为声明,并在其中一个中为其提供定义 cpp文件。否则,变量在每个包含标题的编译单元中声明,这不是您要查找的效果。
P.S。我假设您知道为什么全局变量不好,对吗?
答案 3 :(得分:2)
“ 我有4个文件 ”。
让我在那里阻止你。我同意你有四个文件,但这并不是真的相关。您有两个 翻译单元。翻译单元是输入编译器的文本量。您的翻译单元,我们称之为 MAIN 和 SOMETHING ,分别包含预处理文件main.cpp
和something.cpp
的结果。
预处理后,每个翻译单元都包含一行int *sth;
此行声明并定义变量sth
。
单定义规则要求您在整个程序中只有sth
的一个(不多于,不少于)定义。为了实现这一目标,您必须在一个翻译单元中只有一个源代码行int *sth;
,并且根据需要只需要extern int *sth;
个。{/ p>
在您的情况下,我会将int *sth;
放在MAIN中,extern int *sth;
放在SOMETHING中。此外,你可以拥有尽可能多的extern int *sth;
副本 - 它们不会伤害任何东西。
现在,回到你的四个文件。您应该将extern int *sth;
放入shared.h
。这意味着MAIN和SOMETHING都会有extern
行。您还应将int *sth;
放入main.cpp
,以便MAIN具有定义。
你有:MAIN和SOMETHING都有extern
行,所以他们都指的是同一个变量。 MAIN也有一个定义。所以sth
变量只有其中一个。
<小时/> 除了:为什么
static int *sth;
中shared.h
做错了什么?
因为两个翻译单元中的每一个都看到了他们自己的static
声明。 static
声明减少了声明名称与单个翻译单元的链接。
答案 4 :(得分:1)
您不希望将其设为静态全局,因为它会在每个翻译单元中创建本地sth
,而您只将其分配为一个。这就是它在Foo::printVar
中崩溃的原因,因为它是一个未初始化的指针。
您希望在共享标头中将其声明为extern int* sth;
,然后将int* sth;
放在main之前或至少在其中一个位置使用之前。
实际上,如果你真的需要一个全局可访问的对象,在堆上分配,并且你想要共享它,那么它可能会更好extern std::shared_ptr<int> sth;
。在其中一个CPP文件中将其定义为std::shared_ptr<int> sth;
,并调用std::make_shared
进行分配。这样,当使用它的最后一个对象超出范围时,将自动处理释放内存。