Variable already defined in .obj; What is going on here?

你离开我真会死。 提交于 2019-12-20 02:32:08

问题


head.h


#pragma once

namespace foo
{
    int bar;

    int funct1();
}

head.cpp

#include "head.h"

int foo::funct1()
{
    return bar;
}

main.cpp

#include <iostream>

#include "head.h"


int main()
{
    foo::bar = 1;
    std::cout << foo::funct1() << std::endl;
    return 0;
}

Error LNK2005 "int foo::bar" (?bar@foo@@3HA) already defined in head.obj

I don't understand what is going on. I tried looking for the answer but everyone's questions are so specific to their code and don't even look close to the problem that I am having.

I am not including .cpp files into main. I am not redefining anything. I am literally just assigning 1 to the variable then returning it with a function in the same namespace. How is it being defined multiple times?


回答1:


The header head.h is included in two compilation units head.cpp and main.cpp. So the variable bar is defined twice. You could declare the variable without its definition the following way

#pragma once

namespace foo
{
    extern int bar;

    int funct1();
}

and then define it in some cpp module.




回答2:


This foo namespace-level bar declaration:

namespace foo
{
    int bar;
}

is actually a definition.

To make it a declaration, mark the bar as extern in head.h:

namespace foo
{
    extern int bar;
}

Then define it in head.cpp:

int foo::bar = 0;



回答3:


head.h is included in both main.cpp and head.cpp. So the variable is defined twice.

Possible Solution: make it inline. The "extern" solutions are also good, although older in approach.

namespace foo
{
    inline int bar;
}



回答4:


How is it being defined multiple times?

It is defined once in head.cpp and once in main.cpp. That is a total of two times. This violates the one definition rule, which states that there may only be one definition for every variable.

int bar;

This is a definition of a variable. You've included it into two translation units.

A variable can be declared without definition in an extern declaration:

extern int bar;

Replace the definition with such declaration, and put the definition into exactly one translation unit.




回答5:


I am not redefining anything. I am literally just assigning 1 to the variable

You're redefining the variable!

head.cpp has one via #include "head.h", and main.cpp has one via #include "head.h".

You need to merely declare it (unusual but not too strange) in the header:

extern int bar;

…then define it in one translation unit. This is just like what you do with static class members (albeit with slightly different syntax).

Since C++17, you may do this by instead plopping the inline keyword on to your definition.

Alternatively, avoid mutable globals…




回答6:


Do carefully note that foo is not a class, but a namespace. When you declare a free variable in the header file:

int bar;

And then #include this header file multiple times (into different CPP files, causing multiple translation unit compilations), you'd get a linker error. Everyone knows it.

And, you'd add extern attribute at the declaration, and define the variable elsewhere in one of the CPP/C file.

Putting a global variable into a namespace is nothing but giving the global variable a different name. Think if foo::bar as foo__NS__bar, and hence you must add extern in the header and define foo::bar at some locatoin.

Note that this is different from a non-static member variable of a class. A class variable doesn't need to be defined/declared this way since the class is a type. Each instantiated variable of class-type would have a separate copy of the variable. Further to that, when you add a static variable in the class, you are giving that logically global variable another name. Thence, you must have that static-variable defined one of the CPP file.




回答7:


The problem is you are defining foo::bar more than once: in header.h and in main.cpp. It's a global variable that's being defined more than once, and that's not possible. So the linker complains that you are defining it multiple times.

You can fix this by declaring foo::bar with extern:

namespace foo
{
    extern int bar;

    int funct1();
}

Then define it in header.cpp:

int foo::bar;


来源:https://stackoverflow.com/questions/56735173/variable-already-defined-in-obj-what-is-going-on-here

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