精华内容
下载资源
问答
  • cppobj再到exe,重定义的问题

    千次阅读 2017-03-29 10:15:50
      include的目的是我们可能会当前的cpp中使用其他cpp定义的东西,但是我们不可以直接include该cpp,因为这会导致链接的时候出现重定义的错误(cpp本身有一份定义,又被别人include了一份定义,链接的时候就...

    这里写图片描述

    上述过程分为两步:
    (1)每个cpp先生成各自对应的obj即编译单元;
    (2)最后通过链接器把所有obj链接成一个exe形成一个程序。
    而重定义在这两步之中都可能发生。
    第一步中,如果一个cpp内不小心定义了多份(>=2)相同数据,在生成obj,还没链接前就已经报错了。
    第二步也是最常出现重定义的地方。你可能不小心地在两个cpp中定义了相同的数据,各自生成obj的时候并不会报错,但是当链接的时候就会出现重定义。或者你的项目的多份cpp都include了同一份.h文件,而这个.h文件存在定义,一样的,在各自生成obj的时候不会报错(如果没有其他的重定义的话),但是当链接的时候就会报错。

    展开全文
  • xxx已经在obj中定义

    万次阅读 多人点赞 2019-07-11 14:57:32
    唉。记性是一年不如一年了,这种错误一看就是儿科错误,为什么还犯呢。...1.我们知道编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其中一项工作便是将你源程序#include的头文...

    唉。记性是一年不如一年了,这种错误一看就是儿科错误,为什么还在犯呢。。。为不长记性孩子的未来感到担忧。。。。


    很明显是重复定义了,一般在c++的项目开发时,菜鸡很容易出现这种错误。来看看常见的情况是什么:

    1、头文件重复包含;2、变量重复定义

     

    头文件重复包含

     1.我们知道在编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其中一项工作便是将你源程序中#include的头文件完整的展开,如果你有意或无意的多次包含相同的头文件,会导致编译器在后面的编译步骤多次编译该头文件,工程代码量小还好,工程量一大会使整个项目编译速度变的缓慢,后期的维护修改变得困难。
     2.第一点讲的头文件重复包含的坏处其实还能忍,毕竟现在计算机运算能力已经不是早些时候那么慢了。但是头文件重复包含带来的最大坏处是会使程序在编译链接的时候崩溃,这是我们无法容忍的。


    来看个例子:
     

    //a.h
    #include<stdio.h>
    int A=1;
     
     
    //b.h
    #include "a.h"
    void f(){printf("%d",A);}
     
    //main.c
    #include<stdio.h>
    #include"a.h"
    #include"b.h"
    void main(){f();}
    

    此时输入gcc -c main.c进行编译,会提示A重复定义,程序崩溃:

    然后输入gcc -E main.c -o main.i看下预处理内容:

    可以看到6015行和6021行重复出现int A=1;的定义,违背了一次定义的原则,所以会出错。

    了解了头文件重复包含的坏处,那么如何避免它呢?
    通常有两种做法:条件编译和#pragma once
    条件编译就是通常的
    #ifndef _XXX
    #define _XXX
    ...
    #endif
    具体怎么用,可以google。这里介绍下#pragma once:#pragma once这种方式,是微软编译器独有的,也是后来才有的,所以知道的人并不是很多,用的人也不是很多,因为他不支持跨平台。如果你想写跨平台的代码,最好使用条件编译。如果想使用#pragma once,只需在头文件开头加上#pragma once即可。

    两者的联系与区别:
     联系是都可以避免头文件重复包含,区别主要在于两者避免头文件重复包含的实现方式上。
    再看上面的例子:
    暂不考虑b.h,将main.c中变为:

    #include<stdio.h>
    #include "a.h"
    #include "a.h"
     
    void main()
    {
       printf("%d",A);
    }
    

    1.在a.h中加入条件编译:

    //a.h
     
    #include<stdio.h>
    #ifndef _A_H
    #define _A_H
     
    int A = 1;
     
    #endif;
    

     

    2.在a.h 中加入#pragma once:

    //a.h
     
    #pragma once
    #include<stdio.h>
    int A = 1;
    

    虑情况1条件编译:

    编译main.c时,预处理阶段遇到①,编译器打开a.h,发现_A_H未定义,于是将 #define到#endif之间的内容包含进main.c;当遇到②时,编译器再次打开a.h,发现_A_H已经定义,于是直接关闭a.h,a.h没有再次包含进main.c,从而避免了重复包含。
    考虑情况2#pragma once:
    预处理阶段遇到①时,打开a.h,将#pragma once后面的内容包含进main.c中,关闭a.h。遇到②时,编译器直接跳过该语句,执行后面的语句,从而避免重复包含。

    讲完了文件的重复包含,让我们来思考一个问题:如前所说,避免头文件的重复包含可以有效地避免变量的重复定义,其实不光是变量的重复定义,也可以避免函数和类、结构体的重复定义。但是
    避免头文件的重复包含是否一定可以避免变量、函数、类、结构体的重复定义?
    答案当然是否!


    变量重复定义

    让我们再看上面的例子:

    //a.h
     
    #include<stdio.h>
    #ifndef _A_H
    #define _A_H
     
    int A = 1;
     
    #endif;
    
    //b.h
     
    #include<stdio.h>
    #include "a.h"
    void f();
     
    //b.c
     
    #include"b.h"
    void f()
    {
       printf("%d",A+1);
    }
     
    //c.h
     
    #include<stdio.h>
    #include "a.h"
    void fc();
     
    //c.c
     
    #include"c.h"
    void fc()
    {
       printf("%d",A+2);
    }
    
    //main.c
     
    #include<stdio.h>
    #include "b.h"
    #include "c.h"
    void main()
    {
        fb();
        fc();
    }
    

    然后分别编译gcc -c b.c -o b.o和gcc -c main.c -o main.o,并未提示任何错误。
    但是当生成可执行文件时候gcc b.o main.o -o main,编译器提示出错:

    为什么会出错呢?按照条件编译,a.h并没有重复包含,可是还是提示变量A重复定义了。
    在这里我们要注意一点,变量,函数,类,结构体的重复定义不仅会发生在源程序编译的时候,在目标程序链接的时候同样也有可能发生。我们知道c/c++编译的基本单元是.c或.cpp文件,各个基本单元的编译是相互独立的,#ifndef等条件编译只能保证在一个基本单元(单独的.c或.cpp文件)中头文件不会被重复编译,但是无法保证两个或者更多基本单元中相同的头文件不会被重复编译,不理解?没关系,还是拿刚才的例子讲:
    gcc -c b.c -o b.o :b.c文件被编译成b.o文件,在这个过程中,预处理阶段编译器还是会打开a.h文件,定义_A_H并将a.h包含进b.c中。
    gcc -c c.c -o c.o:c.c文件被编译成c.o文件,在这个过程中,请注意预处理阶段,编译器依旧打开a.h文件,此时的_A_H是否已被定义呢?前面提到不相关的.c文件之间的编译是相互独立的,自然,b.c的编译不会影响c.c的编译过程,所以c.c中的_A_H不会受前面b.c中_A_H的影响,也就是c.c的_A_H是未定义的!!于是编译器再次干起了相同的活,定义_A_H,包含_A_H。
    到此,我们有了b.o和c.o,编译main.c后有了main.o,再将它们链接起来生成main时出现问题了:
    编译器在编译.c或.cpp文件时,有个很重要的步骤,就是给这些文件中含有的已经定义了的变量分配内存空间,在a.h中A就是已经定义的变量,由于b.c和c.c独立,所以A相当于定义了两次,分配了两个不同的内存空间。在main.o链接b.o和c.o的时候,由于main函数调用了fb和fc函数,这两个函数又调用了A这个变量,对于main函数来说,A变量应该是唯一的,应该有唯一的内存空间,但是fb和fc中的A被分配了不同的内存,内存地址也就不同,main函数无法判断那个才是A的地址,产生了二义性,所以程序会出错。

     

     


     

    讲了这么多,那么到底怎么样才能避免重复定义呢?
    其实避免重复定义关键是要避免重复编译,防止头文件重复包含是有效避免重复编译的方法,但是最好的方法还是记住那句话:

    头文件尽量只有声明,不要有定义!!!!!!!!!!!!!!!!!!!!!!!!!!

    这么做不仅仅可以减弱文件间的编译依存关系,减少编译带来的时间性能消耗,更重要的是可以防止重复定义现象的发生,防止程序崩溃。
     


    转载博客:https://blog.csdn.net/u014557232/article/details/50354127

     

    展开全文
  • error LNK2005 已经 obj 中定义 错误

    千次阅读 2015-03-11 12:53:33
    >> : error LNK2005: ×××× (★★★★) 已经 ※※※.obj 中定义   通常是由于.h文件里定义了此变量,移动到.cpp文件里即可。 并使用到这个变量的cpp文件加上extern int ID;   ...

    >> : error LNK2005: ×××× (★★★★) 已经在 ※※※.obj 中定义

     

    通常是由于在.h文件里定义了此变量,移动到.cpp文件里即可。


    并在使用到这个变量的cpp文件中加上extern int ID;

     

    出错原因:

    无意中遇到了这样的编译问题, 于是google,发现在.h文件里定义变量,发生这问题的概率是灰常大的.

     

    下面这段红字是参考网上的说法:

     

    当你第一个使用这个头的.cpp文件生成.obj的时候,int i 在里面定义了当另外一个使用这个的.cpp再次[单独]生成.obj的时候,int i 又被定义然后两个obj被另外一个.cpp也include 这个头的,连接在一起,就会出现重复定义.

     

    不过经过一轮研究发现.. 其实这说法不怎么正确.. 最起码对VS来说..

    经过实验, 发现只要有两个cpp同时包含一个定义了变量的.h文件,就会提示错误.

     

    再回想下刚 考完的编译原理, obj是什么?  其实就是cpp翻译后的一坨中间代码.. 一般编译过程就是把cpp先翻译成obj, 最后把obj再连接成exe. 这样,不管中间有没有第三者把前两个连接一起, 最终obj还是会汇集在一起.. 下面可以看到,错误发生在链接,而不是翻译..

     

    正在链接...
    1>3.obj : error LNK2005: "int i" () 已经在 2.obj 中定义
    1>D:\编程之美\vs2008代码\dfsdfadsfec\Debug\dfsdfadsfec.exe : fatal error LNK1169: 找到一个或多个多重定义的符号

     

     

    本人得出的结论:

    只要两个或者以上的.cpp同时包含了一个定义了变量的.h文件,就会提示错误.

    不过注意, 这中间可能会包含些比较复杂的逻辑关系.. 

    例如我的那坨代码.. 

    假定一个定义了变量的1.h文件

    有1.cpp和2.cpp, 1.cpp包含1.h,   2.cpp只包含2.h  但是2.h包含了1.h..  所以1.h中定义的变量编译的时候会在2.pp中有定义. 于是乎2.cpp翻译成的obj里也会有定义, 结果导致提示obj里重定义.

    在头文件和cpp文件错中复杂的情况下, 根本就很难判断其祸根源.

    所以得出结论:

    没事就别在.h中定义变量,或者初始化静态成员变量(我就是后一种情况).

    不过有种比较酷的做法, 就是直接改成.c编译.  据说c里遇到重定义,  会忽略为声明.

    展开全文
  • error LNK2005:"XXX已经 XXX.obj 中定义 目前处理祖传代码,由于未创建头文件,我直接main.cpp中#include "xx.cpp"导致出现错误报告 错误 LNK2005 “int __cdecl playMain(void)” (?playMain@@YAHXZ) 已经 ...

    error LNK2005:"XXX已经在 XXX.obj 中定义

    目前在处理祖传代码,由于未创建头文件,我直接在main.cpp中#include "xx.cpp"导致出现错误报告

    错误	LNK2005	"int __cdecl playMain(void)" (?playMain@@YAHXZ) 已经在 play.obj 中定义
    

    原因可能为C++规定不允许有同名的外部函数,链接的时候链接器会发现在xxx.obj和main.obj中定义了同一个函数,会直接报错。
    在这种情况下,尝试两种解决方案:

    1. 再建一个与之同名的"***.h"头文件,只复制.cpp文件中各种(类,函数,带extern的变量)的声明,其他的函数实现等都不复制
    2. 在调用函数前加了static ,编译成功且调用函数成功。
      在这里插入图片描述

    所以对此有了疑问,一般来说定义的函数前为extern才可以被其他cpp文件调用,为何用了static才能成功调用?

    ———————————————————————————————————————————————————————
    原因是因为在上一次运行时已经将extern修饰的playMain()传入主函数,所以static修饰后能运行,但此时无法修改已经在main.obj中的playMain函数。所以该方法不可取。

    展开全文
  • 然后A.cpp包含了该.h,B.cpp包含了该.h,于是链接的时候,生成A.obj,B.obj,但是 .h中定义的变量会这两个obj中又被定义,所以,导致了这个LINK2005错误。 解决方法:不要.h中定义变量!!.h中只声明函数,...
  • error:LNK2005 已经*.obj中定义

    万次阅读 2016-01-15 14:23:20
    实习项目涉及到静态库的编写,用实例调试静态库的时候,遇到LNK2005重复定义错误:已经“*.obj中定义。 上网搜了一下,总结有如下几种情况: 1、重复定义全局变量 全局变量是针对整个工程的,一个CPP...
  • 近来写工程:想把一个变量多个cpp文件使用,写了类似如下代码: main.cpp: #include "A.h" #include "B.h" extern w;//对w的extern声明 main() { do(w);//对W进行操作 } A.h: w;//w的声明 B.h #include...
  • 注意,.h文件应最好只包含声明而无定义,因为.h文件可能会被.cpp文件引用多次,这样会产生“重定义”的错误,同时可以使含main函数的.cpp文件更加简洁。 如图: | | | | | | | | 其他...
  • 问题:项目编程过程,想...2、变量、函数定义放在func.cpp,声明放在func.h; // File:func.c int i = 0, j = 2;// 本文件全局变量 // 功能函数 int func(void) { return 0; } // File:func.h #pragma o
  • >main.obj : error LNK2005: "void __cdecl Creat_graph(struct ...Creat_graph@@YAXPAUgraph@@@Z) 已经 graph.obj 中定义 1>main.obj : error LNK2005: "int * visit" (?visit@@3PAHA) 已经 graph.obj 中定义 1>
  • .h中定义的全局变量移到.cpp中
  • “error LNK2005: 已经*.obj中定义”  编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难解决的错误,弄清楚它形成的原因,就可以轻松解决它了。造成LNK2005错误主要有以下几种情况:...
  • C++中的“error:LNK2005 已经*.obj中定义”异常问题  异常现象如下:   C++中的“error:LNK2005 已经*.obj中定义”异常问题(图1)  “error LNK2005: 已经*.obj中定义”  编程中经常能遇到LNK...
  • C++ error:LNK2005 已经*.obj中定义

    万次阅读 2016-06-07 23:01:36
    test2@@YAXXZ) 已经 源2.obj 中定义 fatal error LNK1169: 找到一个或多个多重定义的符号 问题在于没有把握清楚头文件的作用以及CPP之间函数与变量命名方式的规则: 头文件的内容: ★ 类型
  • vs2017中 c++ “error LNK2005: 已经*.obj中定义” 错误

    千次阅读 多人点赞 2019-04-09 10:56:47
    vs2017中 c++ “error LNK2005: 已经*.obj中定义” 错误 符号对象中已定义 符号符号已多次定义。 此错误后跟错误LNK1169。 解决办法 属性->配置属性->链接器->命令行中添加 /FORCE:MULTIPLE 即可 ...
  • 然后A.cpp包含了该.h,B.cpp包含了该.h,于是链接的时候,生成A.obj,B.obj,但是 .h中定义的变量会这两个obj中又被定义,所以,导致了这个LINK2005错误。  解决方法:不要.h中定义变量!!.h中只声明函数...
  • 错误 LNK2005 “public: __thiscall已经 main.obj 中定义 解决办法:这个问题就是vs自动生成的构造函数和析构函数没有删除移动到cpp文件而该hpp文件又被引用了 构造函数从.h文件修改到.cpp文件下可以解决。
  • “error LNK2005: 已经*.obj中定义”   编程中经常能遇到LNK2005错误——重复定义错误,其实LNK2005错误并不是一个很难解决的错误,弄清楚它形成的原因,就可以轻松解决它了。  造成LNK2005错误主要有以下...
  • error:LNK2005 _main 已经 *.obj 中定义

    万次阅读 2017-06-13 00:03:38
    正确的应该是一个CPP文件中定义如下:int g;那么使用的CPP文件就应该使用:extern int g (1)声明必须使用extern关键字; (2)不能给变量赋初值 2.头文件的包含重复。此时应该头文件设置 相关的宏
  • 本人遇到的情况: 1、该函数定义在了头文件:把该函数的声明和定义分开,声明头文件定义在.cpp文件。 未完待续。。。
  • 错误 LNK2005 xxx已经 xxx.obj 中定义

    千次阅读 2020-06-03 21:49:38
    写了一个main.cpp 一个Singleton.h和一个Singleton.cpp Singleton.h #pragma once class Singleton { public: static Singleton* GetInstance() { if (m_Instance == nullptr) m_Instance = new Singleton();...
  •  多重包含含有变量定义的.h文件所造成  这个现象很容易重新,首先新建一个1.h文件,然后里面写下如下代码 #pragma once int i = 0; 然后新建一个1.cpp,里面代码如下: #include "1.h" 再新建一个2.cpp,代码...
  • vs error lnk2005 test.obj:”struct MyStruct *”已经map.obj中定义原因分析 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式丰富的HTML页面。 头文件map.h中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 43,502
精华内容 17,400
关键字:

在cpp中定义obj