LNK2005错误,已在main.obj中定义

LNK2005 error, already defined in main.obj

本文关键字:obj 定义 main 已在 错误 LNK2005      更新时间:2023-10-16

所以我写代码已经有一段时间了,我不是世界上最好的程序员。我还在学习,认为自己是个初学者。我正在用c++为一个概念类写一篇词法分析。我尝试了在类似网站上看到的解决方案,例如在头文件中使用extern和在cpp文件中使用const,但注意到工作。当我将头文件包含在两个单独的.cpp文件中时,我会对头文件中的所有int都出现此错误:

tokens.obj:错误LNK2005:"int eND"(?eND@@3HA)已在main.obj 中定义

头文件=

#include <string.h>
#include <map>
using namespace std;
extern int lANGLE=1, rANGLE=2,iD=3, eQ=4, sLASH=5, qSTRING=6, oTHER=7, eND=8, tEXT=9;
map <int, int> counter;
extern int getToken(istream *br, string& lexeme);

token.cpp(声明getToken的作用)

#include "suffix.h"
#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
bool slash = false;
bool text = false;
bool quote = false;
bool id = false;
bool equ =  false;
bool other = false;
bool qstring = false;
char prev=NULL;
int getToken(istream *in, string& lexeme)
{
    char c;
    char prev;
    lexeme="";
    int intSlash = 0;
    int intText = 0;
    int intQuote = 0;
    int intId = 0;
    int intEqual = 0;
    int intOther = 0;
    int intQstring = 0;
    int langlec = 0;
    int  intLangle = 0;
    int ranglec = 0;
    int  intRangle = 0;
    if (in->eof())
        return eND;
    while (in->get(c))
    {
        switch (c)
        {
            case '/' :
                if (quote == false && langlec > 0)
                {
                slash = true;
                intSlash++;
                return 5;
                }
                break;
            case '=' :
                if (quote == false && langlec > 0)
                {
                 equ = true;
                intEqual++;
                return 4;
                }
                break;
            case '<' :
                if (  prev != ' '  && langlec == 0) 
                    {intText++ ;
                return 9;}
                if (quote == false)
                {
                    langlec ++;
                    intLangle ++;
                    id = true;
                    return 1;
                }

                break;

            case '>' :
                if (quote != true)
                {
                    ranglec++;
                    intRangle++;
                    return 2;
                    if (langlec > 0)
                    {
                        langlec--;
                        id = false;
                    }
                }   
                break;
            case '"' :
                if (langlec > 0 && quote == true)
                {
                    quote = false;
                    id = true;
                    intQstring ++;
                    intOther--;
                    return 6;
                }
                else if (langlec > 0)
                {
                    intOther++;
                    quote = true;   
                    return 7;
                }

                break;
            case ' ':
                if ( prev != ' ' && prev != '<' && prev != '>' && quote == false){
                    if (langlec == 0){
                        intText++;
                        return 9;
                    }
                }
                    else if ( prev != '/' && prev != '=')
                        {intId++;
                        return 3;
                    }
                break;
            default:
                if (quote == true)
                    {
                        id = false;
                    }
                else if (id==true) 
                    {
                        intId++;
                        id=false;
                        return 3;
                    }
                prev=c;
        }
    }
return 0;
}

main.cpp

#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
#include <string>
#include <algorithm>
#include "suffix.h"
using namespace std;
int
main( int argc, char *argv[] )
{
 istream *br;
 ifstream infile;
 // check args and open the file
if( argc == 1 )

br = &cin;
 else if( argc != 2 ) {
cout<<"THERE IS A FATAL ERROR"<<endl; 
return 1; // print an error msg
 } else {
 infile.open(argv[1]);
 if( infile.is_open() )
 br = &infile;
 else {
 cout << argv[1] << " can't be opened" << endl;
 return 1;
 }
}
string tokens="";
int typeOfToken;
while(true){
    typeOfToken=getToken(br,tokens);
    if (counter.count(typeOfToken))
        counter[typeOfToken]+=1;
    else
        counter[typeOfToken]=1;
    if(typeOfToken==8)
        break;
}
cout<<"total token count: "<<endl;
if (counter[1]!=0)
    cout<<"LANGLE: "<<counter[1]<<endl;
if (counter[2]!=0)
    cout<<"RANGLE: "<<counter[2]<<endl;
if (counter[9]!=0)
    cout<<"TEXT: "<<counter[9]<<endl;
if (counter[3]!=0)
    cout<<"ID: "<<counter[3]<<endl;
if (counter[4]!=0)
    cout<<"EQ: "<<counter[4]<<endl;
if (counter[5]!=0)
    cout<<"SLASH: "<<counter[5]<<endl;
if (counter[6]!=0)
    cout<<"QSTRING: "<<counter[6]<<endl;
if (counter[7]!=0)
    cout<<"OTHER: "<<counter[7]<<endl;
return 0;
}
extern int lANGLE=1, ...  eND=8

这应该是extern声明,但由于显式初始化,它实际上是一个定义。因此,您最终在几个翻译单元中定义了所有这些变量,从而违反了"一个定义规则"。

当你解决这个问题时,map <int, int> counter; 也会出现同样的问题

你应该做的是回答自己一个问题,为什么你必须在头文件中声明所有这些。map <int, int> counter;仅在main.cpp中使用,因此将其移动到那里。int变量可以替换为一个enum,因为您似乎要将它们用作getToken()的返回值。

所以它会像一样

enum Token {
    lANGLE=1, rANGLE=2,iD=3,...
};
Token getToken(istream *br, string& lexeme);