简体   繁体   中英

How to avoid linker error

Inside General.h

#ifndef GENERAL
#define GENERAL
namespace counternamespace{
    int upperbound;
    int lowerbound;
}
#endif

Inside Analyzer.h

#ifndef ANALYZER
#define ANALYZER
#include"General.h"

class Analyzer
{
public :
     int var ;
     int func();
};
#endif

Inside Test.h

#ifndef TEST
#define TEST
#include"Analyzer.h" //Error
class Test2
{
public:
    Test2(void);

public:
    ~Test2(void);
};
#endif

In the above code when I don't add Analyzer inside Test.h everything is working fine. But after adding its showing the following linker error.

1>Test2.obj : error LNK2005: "int counternamespace::lowerbound" (?lowerbound@counternamespace@@3HA) already defined in Analyzer.obj
2>Test2.obj : error LNK2005: "int counternamespace::upperbound" (?upperbound@counternamespace@@3HA) already defined in Analyzer.obj

I have added the #ifndef / #endif . Then where I am doing the mistake? Can anyone please let me know?

Yeah, Alok has right. You presumably have Analyser.cpp and Test2.cpp, both are different compilation units. When you call

g++ Analyser.cpp Test2.cpp

the compiler actually makes Analyser.obj and Test2.obj separately and links them together. When the compiler tries to link Analyser.obj and Test2.obj together it realises that the two variables in Test2.obj are present in Analyser.obj too.

Your #define directives do not work since they are present only in a single compilation unit, so General.h is included both in Analyser.obj and Test2.obj.

To avoid such duplicates, the solution is wrapping your namespace variables around with a function. It goes like this:

Inside General.h

#ifndef GENERAL
#define GENERAL
namespace counternamespace{
    int& upperbound();
    int& lowerbound();
}
#endif

inside General.cpp

#include "General.h"
namespace counternamespace{
  int& upperbound(){static int local; return local;}
  int& lowerbound(){static int local; return local;}
}

So you can say now

counternamespace::upperbound()=3;
counternamespace::lowerbound()=1;

and it means the same as you would have said

counternamespace::upperbound = 3;
counternamespace::lowerbound = 1;

don't worry, the compiler will optimise away the function call so there is no overhead either.

You should not define any variables in header files.
A copy of the variables gets created in each translation unit When you include the header file in other files, thus violating the one definition rule and resulting in linking errors.

Inside General.h

#ifndef GENERAL
#define GENERAL
namespace counternamespace{
    extern int upperbound;
    extern int lowerbound;
}
#endif

Inside General.cpp

#include"General.h"
using namespace counternamespace ;
int counternamepace::upperbound = 12;
int counternamepace::lowerbound = 12;

Then do whatever needed .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM