关于VS “error LNK2005: 已经在 .obj 中定义“

1>OpenCVFi.obj : error LNK2005: "class cv::Point_<double> __cdecl reverse(class cv::Point_<double> const &)" (?reverse@@YA?AV?$Point_@N@cv@@ABV12@@Z) 已经在 HalconFi.obj 中定义
 

背景:

项目架构为,主程序A,dll库B,dll库中引用了另外一个dll库C,BC都引用了openCV库,单独编译为添加引用c的b没问题,编译c也测试正常,将c添加到b后编译出错,报错如题所示。

查询发现问题原因应该是这个:https://blog.csdn.net/zhaoyong26/article/details/84635383

但是用了网上的#pragma once,#ifndef,extern都没能解决

经过仔细看代码发现,我的情况是这样的一个全局变量在一个头文件中定义,比如:C.h中定义了全局变量int a = 10;

在一个类的头文件B.h中引用头文件C.h如:include "C.h"

此时就会报题目中的错误。

解决办法:

将include "C.h"从B.h中移到了B.cpp中.

分析:

头文件中不可以放变量的定义!!!一般情况下头文件中只放变量的声明,因为头文件要被其他文件包含(即#include),如果把定义放到头文件的话,就不能避免多次定义变量,C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。

注意头文件中不可以放变量的定义!!!一般情况下头文件中只放变量的声明,因为头文件要被其他文件包含(即#include),如果把定义放到头文件的话,就不能避免多次定义变量,C++不允许多次定义变量,一个程序中对指定变量的定义只有一次,声明可以无数次。

不过有三个例外,以下三种实体的定义也可放到头文件中。

1.值在编译时就已知的const 变量的定义可以放到头文件中

如:const int num10;

2.类的定义可以放到头文件中

3.inline 函数

这三个实体可以定义在多个源文件中,只要在每个源文件中的定义相同。

只要两个或者以上的.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中定义变量,或者初始化静态成员变量(我就是后一种情况).

参考文献:

https://blog.csdn.net/zhaoyong26/article/details/84635383

https://blog.csdn.net/jiangge123456/article/details/20865371

另外整理一个完整的,调整了原版格式,贴在下面,大家一起探讨~

出现上面的错误,只要原因有如下几个:

1.头文件的重复包含

包含的头文件中含有变量、函数、类的定义,在其他使用的地方多次包含,造成重复包含,产生LNK2005错误,

有两种解决方法:

1)使用宏 在头文件head.h中加入

 #ifndef HEAD_H_  //这个地方写法有不少

#define HEAD_H_

......

#endif

2)使用预编译,文件开头加入

#pragma once

2. 使用第三方库造成

主要情形是C运行期函数库和MFC的库冲突造成的。具体的方法就是将提示出错的库放到另一个库的前面。

举例:

#include <WinSock2.h>
//WinSock2.h头文件必须在Windows.h之前
#include <Windows.h>

3. 重复定义全局变量

全局变量是针对整个工程的,在一个CPP文件的定义:int nCount;那么在使用的CPP文件中就应该使用extern int nCount即可,如果还是使用int nCount 就会产生LNK2005错误;

根据C++标准的规定,一个变量是声明,必须同时满足两个条件,否则就是定义:

1)使用extern 关键字  2)不能给变量赋初值
 

如果还是报错的话,只在头文件中声明函数,把函数定义都放到cpp文件中。这里面转自https://blog.csdn.net/wanzew/article/details/81638128出现的问题:

这里我有三个源文件:Base.hpp, Base.cpp 和 main.cpp

在Base.hpp里面定义一个基类,注意,基类只包含构造函数和析构函数的声明,函数在Base.cpp里实现。

此外在Base.hpp中还有一个函数的定义(函数声明和定义都在Base.hpp文件中)三个文件代码如下:

// Base.hpp
#ifndef VIRTUAL_H
#define VIRTUAL_H
 
#include<iostream>
#include<string>
 
using namespace std;
 
class Base{
public:
    Base();
 
    ~Base();
 
private:
    char *p;
};
 
void platform(Base *pBase){
    cout << "this is just a function..." << endl;
}
 
#endif




//Base.cpp
#include"Base.hpp"
 
Base::Base(){
    cout << "construction function..." << endl;
}
 
Base::~Base(){
    cout << "destructor function..." << endl;
    delete p;
}




//main.cpp
#include"Base.hpp"
#include<iostream>
using namespace std;
 
int main(){
    cout << "main..." << endl;
 
    Base * pBase = new Base;
    delete pBase;
 
    system("pause");
    return 0;
}


此时编译会出现一个问题:

1>Base.obj : error LNK2005: "void __cdecl platform(class Base *)" (?platform@@YAXPAVBase@@@Z) 已经在 main.obj 中定义
1>c:\users\wanzew\documents\visual studio 2013\Projects\Class\Debug\Class.exe : fatal error LNK1169: 找到一个或多个多重定义的符号
经过分析,确定了这是由于两个实现文件(main.cpp 和 base.cpp)中重复包含了头文件#include<base.hpp>而造成的。
要注意的是,在这里,在头文件中加入#ifndef……#endif这样的预编译命令是没用的,因为这是防止嵌套包含头文件的,而本例中并没有嵌套包含,是 在两个文件中分别包含。

只在头文件中声明函数,把函数定义都放到cpp文件中,本例中把platform函数的定义从Base.hpp文件中移到Base.cpp文件中
————————————————
版权声明:本文为CSDN博主「Wzning0421」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hanzhen7541/article/details/99681461

其他人的解决方案:

https://social.msdn.microsoft.com/Forums/en-US/2f1a7c23-5981-4526-9b4b-b1322e838716/error-lnk2005-quotvoid-cdecl-bp5voidquot-bp5yaxxz-already-defined-in-testobj?forum=vclanguage

Let's detail a bit:

testDoc.h includes mytest.h

testDoc.h is included by testDoc.cpp and testView.cpp

So once the function bp5 will be compiled in testDoc.obj and once in testView.obj. The #pragma once prevents the header file to be included many times in the same .cpp file not in different cpp files.

You have 2 solutions for this:

1. make the function inline:

inline void bp5() {

int a = 0;

a += 1;

}

2.

put the function in a cpp file and in the header add only:

void bp5();

var code = "bd9610e7-2f2a-4dd0-ab70-a414052825b5"

猜你喜欢

转载自blog.csdn.net/u012422524/article/details/127645265