Repeated Multiple Definition Errors from including same header in multiple cpps

拜拜、爱过 提交于 2019-11-26 18:59:09

Since you're declaring those variables in the header file, and including the header file in each C++ file, each C++ file has its own copy of them.

The usual way around this is to not declare any variables within header files. Instead, declare them in a single C++ file, and declare them as extern in all the other files that you might need them in.

Another way I've handled this before, which some people might consider unpleasant... declare them in the header file, like this:

#ifdef MAINFILE
    #define EXTERN
#else
    #define EXTERN extern
#endif

EXTERN MYSTRUCT Job_Grunt;
EXTERN MYSTRUCT *Grunt = &Job_Grunt;
EXTERN MYSTRUCT Job_Uruk;
EXTERN MYSTRUCT *Uruk = &Job_Uruk;

Then, in one of your C++ files, add a...

#define MAINFILE

...before your #include lines. That will take care of everything, and is (in my personal opinion) a lot nicer than having to redeclare all of the variables in every file.

Of course, the real solution is not to use global variables at all, but when you're just starting out that's hard to achieve.

Jeremy Ruten

When you define a variable, the compiler sets aside memory for that variable. By defining a variable in the header file, and including that file into all your source files, you are defining the same variable in multiple files.

Putting the keyword extern before a variable definition will tell the compiler that this variable has already been defined somewhere, and that you are only declaring (i.e. naming) the variable so that other files can use it.

So in your header file you should make all your definitions forward declarations by adding the extern keyword.

extern MYSTRUCT Job_Grunt;
extern MYSTRUCT *Grunt;
extern MYSTRUCT Job_Uruk;
extern MYSTRUCT *Uruk;

extern int Other_data[100];

And then in one (and only one) of your source files, define the variables normally:

MYSTRUCT Job_Grunt;
MYSTRUCT *Grunt = &Job_Grunt;
MYSTRUCT Job_Uruk;
MYSTRUCT *Uruk = &Job_Grunt;

int Other_data[100];

While most of the other answers are correct as to why you are seeing multiple definitions, the terminology is imprecise. Understanding declaration vs. definition is the key to your problem.

A declaration announces the existence of an item but does not cause instantiation. Hence the extern statements are declarations - not definitions.

A definition creates an instance of the defined item. Hence if you have a definition in a header it is instantiated in each .cpp file, resulting in the multiple definitions. Definitions are also declarations - i.e. no separate declaration is needed if for instance the scope of the item is limited to one .cpp file.

Note: the use of the word instantiation here really only applies to data items.

You need to define your variables as extern in the header file, and then define them in a cpp file as well. i.e.:

extern MYSTRUCT Job_Grunt;

in your header file, and then in a cpp file in your project declare them normally.

The header file is only for definitions, when you instantiate a variable in the header file it will try to instantiate it every time the header is included in your project. Using the extern directive tells the compiler that it's just a definition and that the instantiation is done somewhere else.

I also received this error for a function defined in a .h file. The header file was not intended to make declarations of a class but definitions of some functions which are needed in various places in a project. (I may confuse the "definition" and "declaration" usages, but i hope i could give the main idea.) When I put an "inline" keyword just before the definition of the function which give the "multiple definitions" error, the error is avoided.

To expand on what Gerald said, the header is defining an instance of the struct (which is not what you want). This is causing each compilation unit (cpp file) which includes the header to get its own version of the struct instance, which causes problems at link time.

As Gerald said, you need to define a reference to the struct (using 'extern') in the header, and have one cpp file in your project which instantiates the instance.

I too was having this problem some time back. Let me try to explain what solved it. I had a global.h file which had all declaration and need to be included in every cpp file. Instead of including it in every .cpp, I included it in .h. All my ".h" files I have added the lines #ifndef and #define and ended with #endif. This solved MD problem. Hope this works for you too.

This is what worked for me: linking the sources into separate libraries. (My problem was not with creating a program but one/many libraries.) I then linked (successfully) one program with the two libraries I created.

I had two sets of functions (with one depending on the other) in the same source file, and declared in the same single header file. Then I tried to separate the two function sets in two header+source files.

I tried with both #pragma once and include guards with #ifndef ... #define ... #endif. I also defined the variables and functions as extern in the header files.

As Steve Fallows pointed out, the problem isn't with the compilation but rather with linkage. In my particular problem, I could get away with having two sets of functions, each in its own source file, compiling and then linking into two separate libraries.

g++ -o grandfather.o -c grandfather.cpp
g++ -o father.o -c father.cpp
g++ -fPIC -shared -o libgf.so grandfather.o
g++ -fPIC -shared -o libfather.so father.o

This forces me to link my programs with both libgf.so and libfather.so. In my particular case it makes no difference; but otherwise I couldn't get them to work together.

GCC 3.4 and up supports #pragma once. Just put #pragma once at the top of your code instead of using include guards. This may or may not be more successful, but it's worth a shot. And no, this is not (always) precisely equivalent to an include guard.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!