我知道global是不好的,但作为一种实践,这是初始化在多个目标文件之间使用的global类的正确方法吗?
Header 1.h
class test {
int id;
public:
test(int in){
id = in;
}
int getId(){
return id;
}
};
extern test t;
文件1.cc:
#include <iostream>
#include "1.h"
int main(){
std::cout << t.getId() << std::endl;
return 0;
}
文件2.cc:
#include "1.h"
test t(5);
现在,如果我在标题中全局使用extern
而不是static
,该怎么办?
如果我错了,请更正我,但是可以很好地编译,但是在目标文件和最终二进制文件中,我将具有相同static test t(0);
的2个不同的不相关副本?那不好吗?还是链接程序将其整理出来以消除多个副本?
有全局实例,而不是全局类。
您拥有的是一个全局实例。是的,这听起来很对,直到您获得了相互依赖的多个全局实例。然后,真正的乐趣就会开始。
在全局级别将变量定义为'static'意味着该变量将仅在编译单元中定义(即'o'文件),并且链接器不会导出该符号。
换句话说:是的,将有多个具有相同名称的变量,但仅对同一编译单元上的函数可见。
此外,这里的“隐形”并不意味着“无法进入”。您仍然可以提供对变量的访问。例如:
1.h
t
1.cc
struct Test { int value; }; // Class definition
Test& get_test(); // Function declaration
2.cc
#include "1.h"
static Test t; // Variable declared as 'static'
Test& get_t() { return t; };
我全局使用静态方法
#include "1.h" #include <iostream> int main() { std::cout << get_t().value << std::endl; // Static variable accessed }
?
但是您的static test t;
test
需要构造函数的class
参数,因此您需要:
int in
如果将标题中的static test t(0); // or whatever int you want
转换为extern
,则将在每个要导入标题的编译单元中定义一个static
变量。因此,不同的cpp文件中的类将不再通过t“通信”,因为每个类都有它们。这非常容易出错。
此外,在static
中添加static
的定义为header
。当有人包含标头时,不会期望它会创建变量。
[将an extremely bad practice声明为t
是可接受的做法。但是请注意,如果标头具有通用用途,则可能会降低其在其他项目中的可重用性。
您感兴趣的更多信息:
如果将变量声明放在任何函数之外,则将变量声明为'global'。例如:
1.cc
Why global variables should be avoided if possible and when are they ok
从这里开始,您可以在'1.cc'的任何函数中使用该变量。
对于在任何其他文件中使用相同的变量,编译器将需要了解它:
2.cc
int this_is_global;
这里,关键字extern int this_is_global;
告诉编译器该变量已声明为其他地方,让查找它的任务交给链接器。
如果您想在此处添加extern
关键字,则编译器会将其视为新变量,并且链接器将具有两个具有相同名称的变量,并且将发出错误。您的项目第一个除外的所有源文件都需要extern
关键字,以避免重复的符号。
所以通常的做法是将'extern'声明添加到包含文件中:
1.cc
extern
1.h
int this_is_global;
2.cc
extern int this_is_global;
另一方面,关键字#include "1.h"
告诉编译器不执行导出符号。换句话说:该变量仅存在于声明的源文件中。您可以为每个源文件声明一次,并且会有相同名称的不同变量。例如:
1.h
static
1.cc
static int my_var;
2.cc
#include "1.h"
这样,您将最终拥有两个变量“ my_var”,对其中任何一个的更改都不会影响另一个。