【问题标题】:LNK2005 error, already defined in main.objLNK2005 错误,已在 main.obj 中定义
【发布时间】:2014-12-21 11:21:27
【问题描述】:

所以我已经编写了一段时间的代码,但我并不是世界上最好的编码器。我仍在学习并认为自己是初学者。我正在为 C++ 中的概念类编写词法分析。我已经尝试过我在此类网站上看到的解决方案,例如在头文件中使用 extern 并在 cpp 文件中使用 const,但注意到作品。当我将我的头文件包含在 2 个单独的 .cpp 文件中时,所有整数都出现此错误在头文件中:

tokens.obj : error 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;
}

【问题讨论】:

  • 您在标题中定义它,因此它在两个文件中都定义了。您需要在标题中声明它,并且只在其中一个中定义它。

标签: c++


【解决方案1】:
extern int lANGLE=1, ...  eND=8

这应该是extern 声明,但由于显式初始化,它实际上是一个定义。所以你最终在几个翻译单元中定义了所有这些变量,导致违反One Definition Rule

修复此问题后,map &lt;int, int&gt; counter; 也会出现同样的问题

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

所以会是这样的

enum Token {
    lANGLE=1, rANGLE=2,iD=3,...
};

Token getToken(istream *br, string& lexeme);

【讨论】:

  • 如果我将 int 更改为枚举,我是否必须将地图从 map 更改为 map?同样在主类中,我得到一个 int 类型的参数错误与 const tokentype& 类型的参数不兼容在线:“if (counter.count(typeOfToken))”
  • 同样在主类中,我得到一个 int 类型参数的错误与 const tokentype& 类型的参数不兼容在线:“if (counter.count(typeOfToken))”和行计数器 [类型令牌]+=1;没有 operator[] 匹配这些操作数的错误
  • @curryboy127 您不必更改counter 的类型,因为enum 可以隐式转换为int,但不会有任何影响。我对您的代码进行了更改,它编译得很好,请参阅demo
猜你喜欢
  • 2012-04-25
  • 1970-01-01
  • 2015-08-10
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2021-05-28
相关资源
最近更新 更多