Namespaces and includes generate link error - c++

I was playing around with namespaces when I encountered a lnk2005 error. I can't figure out how to get around the error. Here's the error:
1>Source.obj : error LNK2005: "int Chart::Bars::d" (?d#Bars#Chart##3HA) already defined in Chart.obj
1>Source.obj : error LNK2005: "class foo Chart::l" (?l#Chart##3Vfoo##A) already defined in Chart.obj
1>Source.obj : error LNK2005: "int Chart::t" (?t#Chart##3HA) already defined in Chart.obj
1>C:\Users\bnm\dev\examples\play\nmspca\Debug\nmspca.exe : fatal error LNK1169: one or more multiply defined symbols found
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.49
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Here's the code...
Chart.h
#pragma once
#include "foo.h"
namespace Chart
{
int t;
foo l;
namespace Bars
{
int d;
}
}
Foo.h
#pragma once
class foo
{
public:
int ss;
char* h;
};
Chart.cpp
#include "Chart.h"
using namespace Chart;
int main ()
{
l.h = "g";
}
Source.cpp
#include "Chart.h"
using namespace Chart;
int test()
{
l.ss = 0;
return l.ss;
}
When the #include "Chart.h" from Source.cpp is removed the problems goes away. However, Source.cpp needs #include "Chart.h" for the namespace definition.
What's the correct way to express that "namespace Chart" is needed in both Chart.cpp and Source.cpp so that everything compiles?

If you define any objects in a header file and include that header file in multiple translation units, those objects are now defined multiple times. This is the problem you're having. The declarations of t, l, and d introduce objects and you have done so in a header file.
The proper method for supporting namespace scope variables is to declare them as extern in the header file. This makes them declarations only and not definitions. Then, in a single implementation file, define them.
Change Chart.h to:
#pragma once
#include "foo.h"
namespace Chart
{
extern int t;
extern foo l;
namespace Bars
{
extern int d;
}
}
Then in an implementation file, perhaps Chart.cpp, do:
int Chart::t;
foo Chart::t;
int Chart::Bars::d;

Everywhere you're including Chart.h, you're effectively dropping variables t, l, and d into those objects. Declare them as extern, then define them in Chart.cpp

I've had the exact same problem and I found a workarroud.
chart.h becomes:
#pragma once
#include "foo.h"
class Chart{
static int t;
static foo l;
class Bars
{
static int d;
};
};
and define the variables in chart.cpp
int Chart::t;
foo Chart::l;
int Chart::Bars::d;
Ugly, I know, but at least the syntax is the same wherever you need to use the vars.
This way only ONE .obj file is created containing the variables which prevents the multiple definition erros.
I haven't tried if you can declare a static variable on a namespace which could solve the problem.
Edit:
P.S. this solution gives some weird errors on msvc, as if every time it is included, sections of the code reference differente variables
Tested on my own program the static-inside-namespace and it seems to work.
Example.h:
namespace sdl{
static SDL_Surface* screen;
static int xres = 640;
static int yres = 480;
static int bpp = 32;
static int flags = SDL_ASYNCBLIT;
};

Related

Instance of class shared between static libraries (obj files)

I have a C++ application with the following 3 files:
// sample.h
#ifndef sample_h
#define sample_h
#include <stdio.h>
namespace mynamespace {
class sample {
public:
void myprintf(const char* tmp);
};
}
#endif
// sample.cpp
#include "sample.h"
void mynamespace::sample::myprintf(const char* val) {
printf(val);
}
// main.cpp
#include "sample.h"
int main() {
mynamespace::sample sample1; // How to omit this line?
sample1.myprintf("Hello world!");
}
Is it possible to remove the instantiation of sample1 object from main.cpp, and to have it already available (coming from the static library "sample.obj")?
If I move that line to sample.h, then the error I get during compilation is:
"class mynamespace::sample sample1" already defined in sample.obj
If I move that line to sample.cpp, then the error message is:
'sample1': undeclared identifier
Actually I understand why both errors occur, I just don't know what is the solution.
Thanks
Use static declaration:
in sample.h
namespace mynamespace{
class sample {
public:
static sample sample1;
void myprintf(const char* tmp);
};
static sample& sample1 = sample::sample1;
}
then in sample.cpp
mynamespace::sample mynamespace::sample::sample1;
from main.cpp
access the variable
mynamespace::sample::sample1.myprintf("");
mynamespace::sample1.myprintf("");
Specify an extern storage class in the header file:
namespace mynamespace {
// ...
extern sample sample1;
}
And then define it normally in sample.cpp:
mynamespace::sample sample1;
It's possible that on some compilers/operating systems it will be necessary to specify something else, something that's compiler-specific, in order to get external linkage to a data symbol in a library. This is beyond the scope of the C++ standard. Consult your compiler's documentation for more information.

Defining member variable in header without class definition

I've got two files, list.cpp and Header.h. Segments of the files are below. I know that if the header file is for a class, it is setup different. E.g.
class MyClass
{
public:
void foo();
int bar;
};
However, since I'm not really working with a class here (correct me if I'm wrong), am I not able to declare things under public: and private like below?
Also, if I were to place the global variable rescan in the header file as a member variable, below the function definitions, only the main function can see the variable. Why is it not within the scope of the other functions?
list.cpp:
#include <boost/algorithm/string.hpp>
#include <vector>
using namespace std;
vector<int> results;
bool rescan;
int main()
{
vector<vector<string>> list;
int success = readFile(list);
vector<vector<string>> bad = findMe(list);
system("pause");
return 0;
}
vector<vector<string>> findMe(vector<vector<string>> find)
{
rescan = true;
}
Header.h:
#pragma once
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
#include <string>
#include <vector>
std::vector<std::vector<std::string>> findMe(std::vector<std::vector<std::string>>);
#endif
EDIT: I tried this in my header file:
public:
bool rescan;
But I got "syntax error: 'public'
If you want your global to be visible in other translation units (TU) (other files), you have to declare them extern in those other TUs:
Header.h:
// Include guard omitted
extern bool rescan; // Declaration
file.cpp
#include "Header.h"
bool rescan = false; // Definition
// ...
file2.cpp
#include "Header.h" // To see extern bool rescan;
void foo()
{
rescan = true;
}
// ...

Static variable link error, C++

Consider this code.
//header.h
int x;
//otherSource.cpp
#include "header.h"
//main.cpp
#include "header.h"
...
int main()
{
}
In this case compiler erred with the message. "fatal error LNK1169: one or more multiply defined symbols found"
but when I add static before x, it compiles without errors.
And here is the second case.
//header.h
class A
{
public:
void f(){}
static int a;
};
int A::a = 0;
/otherSource.cpp
#include "header.h"
//main.cpp
#include "header.h"
...
int main()
{
}
In this case compiler again erred with multiple declaration.
Can anybody explain me the behavior we static variables in classes and in global declarations?? Thanks in advance.
The issue with the static member variable is that you have the definition occur in the header file. If you #include the file in multiple source files, you have multiple definitions of the static member variable.
To fix this, the header file should consist only of this:
#ifndef HEADER_H
#define HEADER_H
// In the header file
class A
{
public:
void f(){}
static int a;
};
#endif
The definition of the static variable a should be in one and only one module. The obvious place for this is in your main.cpp.
#include "header.h"
int A::a = 0; // defined here
int main()
{
}
Declare x as extern in header.h to tell the compiler that x will be defined somewhere else:
extern int x;
Then define x once in the source file which you think is most fitting.
For example in otherSource.cpp:
int x = some_initial_value;

ABOUT HEADER FILE CREATION ERROR IN C++

i'm creating header file for .cpp file,where it will contain only declaration or prototype of function
here is the threes programs i have written
1.header.h file//where i have declared functions add(,) and sub(,)
#ifndef HEADER_H
#define HEADER_H
#pragma once
int s;
int add(int a,int b);
int sub(int a,int b);
#endif
2.header.cpp,where i have defined functions add(,) and sub(,)
#include<iostream>
#include "header.h"
using namespace std;
int add(int a,int b){
s=10;
int c=a+b+s;
return c;
}
int sub(int a,int b){
int c=a-b;
return c;
}
3.example.cpp
#include<iostream>
#include"header.h"
using namespace std;
void main(){
int a=10,b=20;
int c=add(a,b);
int d=sub(c,a);
cout<<"c"<<c;
cout<<"d"<<d;
//cout<<s;
getchar();
}
here, i declared variable 's' in header.h and defined in header.cpp file ,which is given as addition to variable c in example.cpp file output.
it showing error
header.obj : error LNK2005: "int s" (?s##3HA) already defined in example.obj
Projects\header\Debug\header.exe : fatal error LNK1169: one or more multiply defined symbols found
please help me to resolve this error,i'm working from long time for this...thanks in advance
You get the error, because this line in .h is already a definition:
int s;
You need to have this in header:
extern int s;
And then in exactly one .cpp file, usually one with same base file name as the .h file, you need to have the definition:
int s;
Related: You don't need the extern keyword with function declarations, because they're just declarations, telling compiler that such a function exists somewhere, and you can do that as many times as you like. But if you put a global (non-static, non-inline) function definition (with {} function body instead of ;) to a .h file, you do get similar linker error about multiple definitions.

namespace either undefined or redefined, why?

just a very small program to test how to use the namespace. I divide it into 3 files, since in large product, ns.h is the namespace interface and ns.cpp is the implementation. I cannot put all these stuff into one file.
Here is the code:
//ns.h
#ifndef MY_H
#define MY_H
namespace my
{
int a=1;
int b=0;
void test();
}
#endif
//ns.cpp
#include <iostream>
#include "ns.h"
using namespace my;
//my::a=1;
//my::b=0;
void my::test()
{
std::cout<<a<<std::endl;
}
//testns.cpp
#include <iostream>
#include "ns.h"
int main()
{
std::cout<<my::b<<std::endl;
my::test();
}
If I keep the above code, and compile will get:
testns.obj : error LNK2005: "int my::b" (?b#my##3HA) already defined in ns.obj
testns.obj : error LNK2005: "int my::a" (?a#my##3HA) already defined in ns.obj
If I comment the statement #include "ns.h" I will get undefined error.
D:\mfc\testns.cpp(5) : error C2653: 'my' : is not a class or namespace name
D:\mfc\testns.cpp(5) : error C2065: 'b' : undeclared identifier
D:\mfc\testns.cpp(6) : error C2653: 'my' : is not a class or namespace name
D:\mfc\testns.cpp(6) : error C2065: 'test' : undeclared identifier
Kindly help me if you know how to do this. Thanks a lot.
Headers are for declarations, not definitions. That's nothing to do with the namespace problem.
//ns.h
#ifndef MY_H
#define MY_H
namespace my
{
extern int a, b; // declared, not defined thanks to 'extern'.
void test();
}
#endif
//ns.cpp
#include <iostream>
#include "ns.h"
int my::a=1; // now we provide the actual definitions.
int my::b=0;
void my::test()
{
std::cout << my::a << std::endl;
}
//testns.cpp
#include <iostream>
#include "ns.h"
int main()
{
std::cout << my::b << std::endl;
my::test();
}
You've defined the two variables a and b in ns.h and then the header file is being included in two source files. This violates the one definition rule as the variables are now defined in both the translation units that are including ns.h.
What you need to do is declare variables in the header and define them in a single source file.
To fix the problem, change ns.h to
#ifndef MY_H
#define MY_H
namespace my
{
extern int a;
extern int b;
void test();
}
#endif
In ns.cpp
#include <iostream>
#include "ns.h"
using namespace my;
int my::a=1;
int my::b=0;
void my::test()
{
std::cout<<a<<std::endl;
}
It's not standard practice to define variables in a header file; they are re-defined every time you #include the header, leading to the linker errors that you are seeing.
If you need to share variables between source files (and there's very few good reasons for this), then you should declare them as extern in the header file, and then define them in one of your source files.