错误 LNK2005 结构已在 .obj 文件中定义

Ian*_*Ian -1 c++ compilation pragma include

我一直在尝试处理有关编译单元的问题。

我得到的错误是

1>frtinvxml.obj : error LNK2005: "struct repFieldInfo det_rep_info" (?det_rep_info@@3UrepFieldInfo@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct repFieldInfo frt_rep_info" (?frt_rep_info@@3UrepFieldInfo@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct FormToolbar * tb" (?tb@@3PAUFormToolbar@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct tagDATE_STRUCT dateFrom" (?dateFrom@@3UtagDATE_STRUCT@@A) already defined in Frtinv.obj
... (It goes on for every variable and method in the header...)
Run Code Online (Sandbox Code Playgroud)

这是我得到的唯一错误。以下是所涉及的每个相应类的包含,按从树上最高到最低的顺序...

***Frtinv.hxx***
#pragma once

#include <voyage.ddh>
#include <vsched.ddh>
# ...

struct frtinvType : public frtinv_type
    {
    int     fixCarSeq;
    ...
Run Code Online (Sandbox Code Playgroud)

...

***frtinv.cxx***
//#define _IN_MAIN_
#include <decisionTable.h>
... 

#define RINDEX 2
#define LINDEX 2
#define PINDEX 0

BOOL s_fNeedSaveAfterDelete = FALSE;
static int rateCnt = RINDEX, lumpCnt = LINDEX, pcntCnt = PINDEX;


//------------------------------------------------------------------------
int getPortcar(char *vslCode, int voyNo, int portCallSeq, int berthSeq, int seq, portcar_type *pret)
    ...
Run Code Online (Sandbox Code Playgroud)

...

***frtinvxml.h***
#define _IN_MAIN_

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <zdb.hxx>
#include <opr32.h>
#include <voyage.ddh>
#include <frtinv.ddh> <------ Tried to add these two to the solution, that failed.
#include <frtinv.hxx> <------

void exitGracefully();
std::list<voyage_type> getVoyages();
Run Code Online (Sandbox Code Playgroud)

...

***frtinvxml.cpp***
#include "frtinvxml.h" <------ taking everything from frtinvxml.h

void main(int argc, char *argv[]) {

    InitWinLib (10, 8);
    ...
Run Code Online (Sandbox Code Playgroud)

我的问题源于这样一个事实,即使我将文件放在同一个文件夹/解决方案中,我也无法让它们不定义自己两次。即使使用'pragma once' 关键字。我也尝试使用老式的#define,如果它已经存在,请不要包含......这也不起作用。

您有任何解决方案或建议吗?

use*_*301 6

#pragma once防止在单个编译单元中多次包含标头 - 在这种情况下为 .obj 文件 - 并且错误明确指出 frtinvxml.obj 定义了已经在 Frtinv.obj 中定义的内容。两个独立的对象。两个独立的编译单元。

once在 Frtinv.obj 和 frtinvxml.obj 的情况下完美地工作。两者都只有一个定义,否则源文件将不会被编译。不幸的是,链接器试图将两个 obj 放入相同的输出中。

对此有两种解决方案,具体取决于变量的使用方式,但两者都不要在标头中进行声明。它几乎总是以糟糕的结局结束。

解决方案 1:所有对象共享一个变量

定义:

extern struct repFieldInfo det_rep_info;
Run Code Online (Sandbox Code Playgroud)

在适当的标题中。extern告诉编译器某处det_rep_info将被声明并且编译应该继续使用这个外部det_rep_info.

在 cpp 文件 frtinvxml.cpp、Frtinv.cpp 或包含公共数据的某些第三个 cpp 中,声明

struct repFieldInfo det_rep_info;
Run Code Online (Sandbox Code Playgroud)

然后对其他三个重复变量执行相同操作。

将这些变量放在哪里取决于个人品味、选择和编码标准。编译此文件并将其与其他 .obj 文件链接,以便每个人都可以访问该变量。

解决方案2:所有对象都有自己的私有变量

宣布:

static struct repFieldInfo det_rep_info;
Run Code Online (Sandbox Code Playgroud)

在每个需要它的 cpp 文件中。对所需的所有变量重复此操作。static确保每个det_rep_info只在特定范围内可见。在这种情况下,单个编译单元。这里实际上有一些微妙之处,因此请阅读文档以确保static适合您。

您可以将声明放在标题中,标题的每个包含者都将获得自己的副本,但重要的是要注意标题的每个包含者都将获得一个副本,无论他们是否需要。不要替别人做这个决定。在需要它的 cpp 文件中声明变量。如果你错过了,编译器会抓住它。