Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理
https://www.cnblogs.com/zjutzz/p/4018816.html

在C++中,有时候需要在不同文件中使用同一个变量。对于这类变量如果处理不当,很容易出现“multiple definition of... first defined here”的错误。

例如,定义了如下3个文件:global.h, a.cpp, b.cpp

//global.h: #ifndef _GLOBAL_H_ #define _GLOBAL_H_  const int a=1; int b;  #endif
//a.cpp #include <iostream> #include <stdlib.h> #include "global.h"  using namespace std;  void test1() {      cout<<"test1"<<endl; }
//b.cpp #include <iostream> #include <stdlib.h> #include "global.h"  using namespace std;  void test2() {     cout<<"test2"<<endl; }  void main() {   cout<<"hello world"<<endl; }

执行编译命令:

g++ -o main a.cpp b.cpp

提示错误为:

[chris@zz jojo]g++ -o main a.cpp b.cpp
/tmp/ccc7OcsO.o:(.bss+0x0): multiple definition of `b'
/tmp/ccs7q2VA.o:(.bss+0x0):第一次在此定义

出错原因:a.cpp和b.cpp先分别被编译为.o格式的目标文件,两个目标文件再被链接器链接起来,这当中a.cpp和b.cpp分别进行了一次include,相当于global.h中的代码重复出现了一次。因为a是const类型,所以重新定义也没事;但是b只是普通变量,重复定义显然不行。

显然,一个解决办法是把b定义为const int类型。或者,定义成static int类型也行。

还有一种解决方案,就是把global.h变为global.c文件,a.cpp和b.cpp中不再include它,但是编译的时候把global.c也编译进去,就可以了:

g++ -o main global.c  a.cpp b.cpp

再举一个class相关的例子。比如有Body和Mouth两个类,Body的greet方法会调用Mouth的say方法,而main函数中会调用全局变量body的greet方法。为了只是用一个body和一个mouth对象,可以这么写:

//body.h #ifndef BODY_H #define BODY_H  #include <mouth.h>  class Body { public:     Body();     ~Body();     void greet(); };  extern Body body;   #endif 
//body.cpp #include <body.h>  Body::Body(){}  Body::~Body() {}  void Body::greet() {     mouth.say(); } 
//mouth.h #ifndef MOUTH_H #define MOUTH_H  class Mouth { public:     Mouth();     ~Mouth();     void say(); };  extern Mouth mouth;   #endif 
//mouth.cpp #include <mouth.h> #include <iostream>  using namespace std;  Mouth::Mouth() {}  Mouth::~Mouth() {}  void Mouth::say() {     cout << "Have a Nice day!" << endl; } 
//class.cpp #include <body.h> #include <mouth.h>   Body body; Mouth mouth; 
//main.cpp #include <iostream> #include <body.h> using namespace std;  int main() {     body.greet(); } 

上面代码中的include,虽然都是用的尖括号,但因为编译时可以通过指定include路径,不会出问题~
编译命令:

g++ -I ./ mouth.cpp body.cpp class.cpp main.cpp -o main

能够正常运行。


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理