C++ static bool variable - c++

I can't understand something that causes LNK2005 errors that I've encountered.
Assume that you have a class A:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
bool A::m_someVar = false;
#endif
File A.cpp:
#include "A.h"
void A::foo(){
m_someVar = true;
}
The code above causes a LNK 2005 however the following code doesn't:
File A.h:
#ifndef A_H
#define A_H
class A{
public:
static foo(void);
private:
static bool m_someVar;
};
#endif
File A.cpp:
#include "A.h"
bool A::m_someVar = false;
void A::foo(){
m_someVar = true;
}
Can someone explain why is this happening even though I have include guards? Should I also add #pragma once?
Thanks in advance.
EDIT: here's the compilation error:
"error LNK2005: "private: static bool GameManager::m_isGameOver" (?m_isGameOver#GameManager##0_NA) already defined in Execution.obj"

include guards(both #ifndef and #pragma) doesn't work across compilation units, which is one of the reasons you should never ever ever define anything in a header file, only declare them. Except for templates of course.
A compilation unit is one .cpp-file and all included headers. Each .cpp create an object file containing a middle stage binary representation of the code, this is the compilation stage. These object files are then linked together in the linking stage. Since each .cpp is handled separately in c++ if you have "float foo;" in header.hpp and both a.cpp and b.cpp include header.hpp, how would the compiler know which foo you mean when running the application?

A "static" variable inside a class declaration is actually a declaration for an extern variable that is in the scope of that class. Like every extern variable, it needs a definition in exactly one source file. Otherwise, the linker will complain about it.
You probably include the .h file from more than one source file, so you have more than one definition.

Related

Confusion over inline behavior C++

I am learning C++ and I am confused by inline behavior. On cppreference I found that " function included in multiple source files must be inline". Their example is the following:
// header file
#ifndef EXAMPLE_H
#define EXAMPLE_H
// function included in multiple source files must be inline
inline int sum(int a, int b)
{
return a + b;
}
#endif
// source file #2
#include "example.h"
int a()
{
return sum(1, 2);
}
// source file #1
#include "example.h"
int b()
{
return sum(3, 4);
}
This is a bit confusing to me - I thought that the ifndef guard was doing this job exactly, i.e. preventing problems when the same file was included multiple times. In any case, I wanted to test this, so I prepared the following:
// Sum.h
#ifndef SUM_H
#define SUM_H
int sum(int a, int b);
#endif
// Sum.cpp
int sum(int a, int b){
return a + b;
}
// a.h
#ifndef A_H
#define A_H
int af();
#endif
// a.cpp
#include "sum.h"
int af(){
return sum(3, 4);
}
// b.h
#ifndef B_H
#define B_H
int bf();
#endif
// b.cpp
#include "sum.h"
int bf(){
return sum(1, 2);
}
// main.cpp
#include "sum.h"
#include "a.h"
#include "b.h"
#include <iostream>
int main() {
std::cout << af() + bf();
}
And this works fine as expected. Then I use define the sum function to be inline in sum.cpp and sum.h, and it fails to compile:
"sum(int, int)", referenced from:
bf() in b.cpp.o
af() in a.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can somebody clarify this for me?
The include guard with #ifndef/#define/#endif or with #pragma once only prevents the inclusion for every single translation unit.
Lets assume you have a header like:
#pragma once
void Do() {}
and two *.cpp files which do the include. If you now compile with
g++ source1.cpp source2.cpp
you will get a
multiple definition of Do() in xy line/file
Every source file will compiled "alone" and so the guard is not seen from the second translation unit which was set by the first one. Both translations ( compilations ) are done fully independent. As this, the include guard will not protect anything in this case.
For this it is possible to define a function definition as inline. Now both definitions will be presented to the linker but marked as "weak". The linker now did not complain about the two definitions and only takes one of them ( typically the last! ) which is not important, as both are the same in that case.
So the include guard has the sense, that you can include a file multiple times to one translation unit. This will happen typically only if you indirect include a header. Lets say a.h has the function definition and b.h and c.h each include a.h. If your cpp-file includes now b.h and c.h both of them include a.h. So you have, without include guard, multiple definitions. This is the use case for include guards.
And the opposite problem having a "undefined symbol" if the function is defined inline but not visible in all using translation units:
Example:
Having that file:
inline void sum() {}
void f1() { sum(); }
and compile with -O0 produces, output of nm f1.o|c++filt
0000000000000000 T f1()
0000000000000000 W sum()
We see the symbol for sum defined as weak, so it can be present multiple times in link stage. It will also be used if a second translation unit which did not "see" the definition, will be linked without problems.
But using "-O3" you get:
0000000000000000 T f1()
That is implementation specific to the compiler! A compiler can provide inlined functions. Typically they do not, if higher optimization levels are in use.
As a rule: If a function is defined inline, its definition must be visible to every translation unit before it is used there!
Then I use define the sum function to be inline in sum.cpp and sum.h, and it fails to compile:
When a function is declared inline, its definition must be available in all the translation units that use the function. Defining the function in only one translation unit is not correct. That's why you are seeing the linker errors.
Move the definition of the function to sum.h to resolve the linker errors.
You should read documentation carefully, beside the statement:
function included in multiple source files must be inline
it also says this:
2) The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access).
which you violated in your example hense the error.

Why can't linker see my (definitely defined) externals?

I have a class with a header and a .cpp file. I declare my functions in the header, and define them in the .cpp file, as you would.
Header:
#pragma once
// my #includes
class CDNAGenerator
{
private:
// stuff
public:
CDNAGenerator(int, int);
~CDNAGenerator();
void FilterMeasurementsForOutliers(std::vector<double>& measurement_values);
// plenty more things
};
CPP:
CDNAGenerator::CDNAGenerator( int genes, int chromosomes )
{
// constructor code
}
void CDNAGenerator::FilterMeasurementsForOutliers(std::vector<double>& measurement_values)
{
// function code
}
Then, from a separate project in the same solution I reference the .h file (but not the .cpp - that seems to lead to multiple definition errors):
#include "..\CalibrationTool\DNAGenerator.h"
And call those functions:
CDNAGenerator* dnaGenerator = new CDNAGenerator(30, 0);
dnaGenerator->FilterMeasurementsForOutliers(values);
But I get unresolved external errors for CDNAGenerator::CDNAGenerator(int, int) and for CDNAGenerator::FilterMeasurementsForOutliers(class std::vector > &)
I thought that I had hooked everything up correctly, so can anyone suggest why I would be getting this linker error?
Add the CPP file to the project
What compiler are you using? Gcc (mingw) does'n supprort #pragma once Use code guards to avoid 'multiple definitions'.
#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
...
}
#endif

Linking error (#ifndef doesn't work as expected)

Can't understand what is a problem here:
I have got main.cpp file where I am including:
#include "lexan.h"
...
The lexan.h file:
#ifndef _LEXAN_
#define _LEXAN_
enum Statements ...
//some function prototypes
...
struct TokensList {
Statements statement;
std::string value;
struct TokensList *next;
};
struct TokensList *tokens = NULL;
#endif _LEXAN_
In lexan2.h:
#include "lexan.h"
// and some function prototypes
The problem is that I get the link error 2005:
1>lexan2.obj : error LNK2005: "struct TokensList * tokens" (?tokens##3PAUTokensList##A) already defined in lexan.obj
1>main.obj : error LNK2005: "struct TokensList * tokens" (?tokens##3PAUTokensList##A) already defined in lexan.obj
Where is my mistake? I thought the
#ifndef _LEXAN_
#define _LEXAN_
in the lexan.h file would protect me from such linking problems.
You are creating struct TokensList * tokens in the header file lexan.h and then including the header in both lexan.cpp & lexan2.cpp which violates the One Definition Rule(ODR).
Note that, header guards prevent including the same header in the same Translation Unit. When you create a variable in the header file, a copy of the variable with the same name gets created in every translation unit where you include the header. This leads to multiple same named variables in your project which the linker complains about.
Solution:
If you need to share it across files, you need to use extern.
How to use extern?
Have a look at:
What are extern variables in C?
How to correctly use the extern keyword in c?
You are violating the one definition rule, as hinted in comments.
Header files should declare variables; they should (almost) never define variables. Your header is defining the variable tokens, which means that only one source file in a given program can use the header, which is not what was intended.
I suggest taking a look at What are extern variables in C? for an extensive (possibly too extensive) discussion of how to handle variables in headers.
But the fundamental rule is:
Do not define variables in headers; only declare them.
Of course, that assumes that the global variable is necessary. When you can, avoid them. But when they are necessary, the header should declare, not define, the variable.
Include guards only stop you from processing the same header twice per translation unit (source file).
Let's say you have a header, X.h, which has include guards:
// x.h
#ifndef X_H
#define X_H
// x.h stuff
#endif
You also have A.h and B.h, each of which include X.h:
// a.h
#ifndef A_H
#define A_H
#include "x.h"
// a.h stuff
#endif
// b.h
#ifndef B_H
#define B_H
#include "x.h"
// b.h stuff
#endif
Then we have j.cpp and k.cpp:
// j.cpp
#include "a.h"
#include "b.h"
// j.cpp stuff
// k.cpp
#include "a.h"
#include "b.h"
// k.cpp stuff
Here the include guards prevent x.h from being processed twice within j.cpp, likewise in k.cpp. But x.h is still included twice, once for each translation unit. So if // x.h stuff was this:
int myGlobalInt; // x.h stuff
Although you prevent j.cpp (and k.cpp) from defining this variable twice, each still has defined it once. At link time, the linker finds them both and complains.
What you want — other than avoiding global variables, which you should try to do — is this:
extern int myGlobalInt; // x.h stuff
Now each translation unit gets told "there exists a myGlobalInt somewhere", and you can explicit define it in a single translation unit of your choosing.
Also, don't use those kinds of header guards; names beginning with an underscore followed by a capital, as well as those beginning with two consecutive underscores are reserved.

bool __cdecl func(void) already defined in func.obj

I'm getting
error LNK2005: "bool __cdecl hasLogin(void)" (?hasLogin##YA_NXZ) already defined in B.obj
error. func is declared in B.cpp file, and it's called from A.cpp file. B.cpp is included in A.cpp. Google says that it's not good to include cpp in antother cpp. If I copy/paste func in A.cpp there's no problem. How to solve tsis problem correctly?
PS I'm new to c++, so forgive if the question is dump.
Create a header file named B.h and add the following function declaration:
#ifndef _B_HEADER_
#define _B_HEADER_
bool hasLogin(void);
#endif
Instead of #include "B.cpp" in A.cpp use #include "B.h".
You should generally declare your classes/functions in .h (header) files, and implement them in .cpp files. It's also usually a good idea to put include guards in your .h files so including them multiple times is not a problem. That way your .cpp files can include any .h file without causing any conflicts.
An example; test.h
#ifndef TEST_H
#define TEST_H
class test {
public:
void bop();
}
bool hasLogin();
#endif
and the corresponding .cpp file
#include <iostream>
#include "test.h"
void test::bop() {
std::cout << "bop" << std::endl;
}
bool hasLogin() {
return false;
}
write #pragma once in the .cpp//.h where the error is coming, sometimes it avoids the error.

static char array behaving unexpectedly across classes

I know this will have a easy answer but am stumped. I've simplified the code as much as possible to get to the point.
I have a simple header file, call it a.h
which has the below and nothing more (it acts as a global settings file for all files in my project that choose to include it)
#ifndef A_H
#define A_H
namespace settings{
static char name[16]={'\0'};
}
#endif
I then have another class, with its own header file, lets call it b.cpp (with b.h not shown)
#include "a.h"
void B::doSomething()
{
strcpy(settings::name,"I like Dogs");
}
Lastly, the third class which access' settings::name, call it c.cpp (with c.h not shown)
#include "a.h"
void C::printSomething()
{
printf("Some Girls Say %s\n",settings::name);
}
Alas, all that gets printed is "Some Girls Say ". What gives? I don't understand how settings::name isn't surviving function destruction of B::doSomething() (I can only guess this is the issue). Is strcpy being lazy and just pointing settings::name to where "I Like Dogs" begins rather than actually acting like strdup?
Any help and workaround is much appreciated. Thanks!
EDIT: For further clarity, B.doSomething() is invoked before C.printSomething().
the static keyword links the name into each translation unit it is included in, so each .cpp file basically has its own version of name.
What you want to do is put the name you want to share in one .cpp file (without the static and declare it with extern linkage in the .h file.
so that's:
a.cpp
namespace settings {
char name[16] = { 0 };
}
a.h
namespace settings {
extern char name[16];
}
b.cpp
void B::doSomething()
{
strcpy(settings::name,"I like Dogs");
}
c.cpp
#include "a.h"
void C::printSomething()
{
printf("Some Girls Say %s\n",settings::name);
}
By including that header in two source files, you have two separate storage locations. Including the header is a bit like just pasting that code into the source files. So they each have their own static variable called 'name'.
To get this to do what you want, you need to:
Use extern, not static, in the header. This effectively means each file including the header will expect to reference a variable external to it.
Define the variable in one of your source files. It needs to be defined somewhere, once. Don't use static or extern when defining it.
First of all write in a.cpp
namespace settings{
char name[16];
}
then ensure
B::doSomething()
is called.