I have this situation where I'm trying to pass a map after I populated it, from a file to a class:
A.h - a normal header file where I have a function prototype and a map
#include <unordered_map>
func1();
static std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
A.cpp
#include "A.h"
func1() {
// ...
chunks.insert(pair<glm::ivec3, Chunk*>(pos, chunk));
cout << chunks.size(); // here I have the right size
// ...
}
B.h
#include "A.h"
class B {
public:
my_func();
}
B.cpp
B::my_func() {
// ...
cout << chunks.size(); // size is 0
for (auto& c : chunks) {
// ... do something
}
}
My question is, why in B.cpp chunks map arrives empty? I thought that if I use static this will solve my problem. Thank you for your time!
You are declaring the chunks variable as static in A.h. That is the problem.
Every .cpp that #include's A.h will get its own copy of the chunks variable. That is why chunks is populated in A.cpp but is empty in B.cpp.
If you want to share the chunks variable across translation units, it needs to be declared as extern instead of static, and then defined in one of .cpp files, eg:
A.h
#include <unordered_map>
func1();
extern std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
A.cpp
#include "A.h"
std::unordered_map<glm::ivec3, Chunk*, KeyHasher> chunks;
func1() {
// ...
chunks.insert(pair<glm::ivec3, Chunk*>(pos, chunk));
cout << chunks.size(); // here I have the right size
// ...
}
B.h
class B {
public:
my_func();
};
B.cpp
#include "B.h"
#include "A.h"
B::my_func() {
// ...
cout << chunks.size(); // here I have the right size
for (auto& c : chunks) {
// ... do something
}
}
Related
I have a simple for loop (though it is not the only component within the method) that is compiled with GNU 4.8.1.10 compiler with debugging option is off and optimization levels O-0, O-2 and O-3 distinctively. The loop is as below:
const int iMyConst = 10; // defined in another header
void myFunc(uint8_t ui8InputNum)
{
// some stuff
for(int i=static_cast<int>(ui8InputNum); i<iMyConst; i++)
{ // loop content
}
}
What happens is that, when I call myFunc(10) (equal to iMyConst), the for loop is executed. This is not the expected behaviour. Inside the loop I printed the variable values as well. They are printed as expected but with an exception: i<iMyConst came out to be true where i was printed as 10. Moreover, I forced all process to run on single core, the unexpected behaviour happened again.
I ran the code in debug mode, and saw that the loop is not executed as expected. Then I defined the loop variable as volatile int i, this time the loop is not executed as well.
The problem might sound odd but it is all what happened. What is the cause of this problem? The system is 64-bit and has 12 cores.
// main.cpp
//============================================================================
// Name : loopProblem.cpp
//============================================================================
#include "a.h"
#include "b.h"
#include <iostream>
int main() {
a* myA = new a;
b* myB = new b;
myB->itsA = myA;
myB->dummyFunc();
delete myA;
delete myB;
return 0;
}
// a.h
#ifndef A_H_
#define A_H_
#include <stdint.h>
// #include <cstdint> not available in c++03
class a
{
public:
a();
~a();
void myFunc(uint8_t ui8InputNum);
};
#endif /* A_H_ */
// a.cpp
#include "a.h"
#include "c.h"
#include <cstdio>
a::a()
{
}
a::~a()
{
}
void a::myFunc(uint8_t ui8InputNum)
{
// some stuff
for(int i=static_cast<int>(ui8InputNum); i<iMyConst; i++)
{
printf("i: %d, comp: %d\n", i, (i<iMyConst));
}
}
// b.h
#ifndef B_H_
#define B_H_
class a;
class b {
public:
b();
~b();
a* itsA;
void dummyFunc();
};
#endif /* B_H_ */
// b.cpp
#include "b.h"
#include "a.h"
#include <cstddef>
b::b() : itsA(NULL)
{
}
b::~b()
{
}
void b::dummyFunc() {
itsA->myFunc(10);
}
// c.h
#ifndef C_H_
#define C_H_
const int iMyConst = 10;
#endif /* C_H_ */
I have the following four files a.hpp, b.hpp, b.cpp and main.cpp in Ubuntu 16.04LTS that mimic my original files.
a.hpp
#ifndef A_H
#define A_H
#include <iostream>
namespace Utility{
typedef struct _structure{
int v;
int w;
}aStructure;
void foo(){
std::cout << "foo" << std::endl;
}
void goo(){
foo();
}
}
#endif
b.hpp
#ifndef B_H
#define B_H
#include <iostream>
#include "a.hpp"
class bCls{
private:
int x;
public:
void moo(Utility::aStructure s);
};
#endif
b.cpp
#include <iostream>
#include "a.hpp"
#include "b.hpp"
void bCls::moo(Utility::aStructure s){
std::cout << "moo" << std::endl;
}
main.cpp
#include <iostream>
#include "a.hpp"
#include "b.hpp"
int main(){
Utility::aStructure s;
bCls u;
u.moo(s);
return 0;
}
When I try to compile using g++ -std=c++11 b.cpp main.cpp the following error message is thrown:
/tmp/ccwvPrRr.o: In function `Utility::foo()':
main.cpp:(.text+0x0): multiple definition of `Utility::foo()'
/tmp/ccCVJOoH.o:b.cpp:(.text+0x0): first defined here
/tmp/ccwvPrRr.o: In function `Utility::goo()':
main.cpp:(.text+0x23): multiple definition of `Utility::goo()'
/tmp/ccCVJOoH.o:b.cpp:(.text+0x23): first defined here
collect2: error: ld returned 1 exit status
My search resulted in Why am I getting multiple definition error when header included?. But one difference in my code is that a.hpp is required in each of b.hpp, b.cpp and main.cpp.
I am very curious to know what I am doing wrong and the best approach to code in this case and corresponding pitfalls.
Why can't I do something like this in C++?
A.h:
#ifndef A_H
#define A_H
#include "B.h"
struct A {
int a;
};
void doStuff1 (B b); // Error here
#endif
B.h:
#ifndef B_H
#define B_H
#include "A.h"
struct B {
int b;
};
void doStuff2 (A a); // Error here
#endif
I get an error that 'A' was not declared in this scope and the same with 'B'.
I know about forward declaration, but I wanted to see if it was possible to have a set up like this as pass-by-value instead of by reference/pointer. Why does the compiler behave like this, if both A and B are in fact declared by the time the compiler reaches that code?
The basic lesson: Includes are processed before any C++ is parsed. They're handled by the pre-compiler.
Let's say that A.h winds up being included prior to B.h. You get something like this:
#ifndef A_H
#define A_H
// ----- B.h include -----
#ifndef B_H
#define B_H
#include "A.h" // A_H is defined, so this does nothing
struct B {
int b;
};
void doStuff2 (A a); // Error here
#endif
// ----- B.h include -----
struct A {
int a;
};
void doStuff1 (B b); // Error here
#endif
At this point, the C++ compiler can take over and start parsing things out. It will try to figure out what the parameter to doStuff2 is, but A hasn't been defined yet. The same logic holds true going the other way. In both cases, you have dependencies on types that haven't been defined yet.
All of this just means that you have your dependencies out of order. It isn't a problem with pass-by-value. Your types must be defined prior to your methods. That's all - see the example below.
// Example program
#include <iostream>
#include <string>
// data_types.h
struct A
{
int x;
};
struct B
{
int y;
};
using namespace std;
// methods_A.h
void foo(A a)
{
a.x = 3;
cout << "a: " << a.x << endl;
}
// methods_B.h
void bar(B b)
{
b.y = 4;
cout << "b: " << b.y << endl;
}
int main()
{
A first;
B second;
first.x = 0;
second.y = 100;
foo(first);
bar(second);
cout << "A: " << first.x << ", B: " << second.y << endl;
}
Example output
a: 3
b: 4
A: 0, B: 100
You have a circular include. You need to either separate them into different header files, such as having A.h and B.h only declare the struct/classes and having a different header file declare the functions.
The problem can also be solved by using forward declarations and passing by reference instead:
struct A;
struct B;
void doStuff1(A& a);
void doStuff2(B& b);
I declare a Algebra.h file which holds the declaration of an add() function:
#ifndef Algebra_
#define Algebra_
namespace Algebra{
int add(int x, int y);
}
#endif
Then I implement add() as:
Algebra.cpp
#include "Algebra.h"
namespace Algebra{
int add(int x, int y){
return x+y;
}
}
Then I have classes A and B, which include Algebra.h:
B.h
#ifndef B_
#define B_
#include "Algebra.h"
#include <iostream>
class B{
public:
void func(int x, int y);
};
#endif
B.cpp
#include "B.h"
void B::func(int x, int y){
int val = Algebra::add(x,y);
std::cout << "B : "<< val << std::endl;
}
A.h
#ifndef A_
#define A_
#include <iostream>
#include "Algebra.h"
#include "B.h"
class A{
public:
void func(int x, int y);
};
#endif
A.cpp
#include "A.h"
void A::func(int x, int y){
int val = Algebra::add(x,y);
std::cout << "A : " << val << std::endl;
}
main.cpp
#include "A.h"
#include "B.h"
#include "Algebra.h"
int main(){
A a;
B b;
a.func(3,4);
b.func(3,4);
int val = Algebra::add(3,4);
std::cout << "main : " << val << std::endl;
}
I tried compilation using
g++ A.cpp B.cpp main.cpp -o bin
g++ A.cpp B.cpp Algebra.cpp main.cpp -o bin
I get this error:
/tmp/ccBXhev4.o: In function 'Algebra::add(int, int)':
main.cpp:(.text+0x0): multiple definition of 'Algebra::add(int, int)'
/tmp/ccfaCF5H.o:A.cpp:(.text+0x0): first defined here collect2: error:
ld returned 1 exit status
I even tried inlining the add() function in Algebra, but still get the error. Also I don't want to make Algebra be a class.
Why am I getting a multiple definition error even though I am adding the Algebra header file, and it does not define but only declare?
Sorry for the noob question..
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax();
std::string ay(std::string jj);
};
struct B {
struct A* f;
int bx() {
return f->ax();
}
std::string by(std::string jj){
return f->ay(jj);
}
};
#endif // DEVF_H
devf.cpp
#include "devf.h"
int A::ax() {
return 5;
}
std::string A::ay(std::string jj){
return jj;
}
I get this error:
multiple definition of `A::ax()'
multiple definition of `A::ay(std::string)'
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp
Try doing this with your code:
devf.h
#ifndef DEVF_H // Add this line
#define DEVF_H // Add this line
// #include <iostream> // removed this as not needed from what is shown
#include <string> // added this as is needed
struct A {
int ax() const; // added const as it doesn't change
std::string ay( const std::string& jj ) const; // changed string to const ref & added const
};
struct B {
/*struct*/ A* f; // keyword struct not needed here.
int bx() const { // added const
return f->ax();
}
std::string by( const std::string& jj ) const { // changed to const ref & added const
return f->ay( jj );
}
};
#endif // !DEVF_H // Add this line
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
Then you asked this or made this statement:
How can I solve this problem? I want the definitions of ax and ay functions in header file and the implementions in .cpp
devf.h
#ifndef DEVF_H
#define DEVF_H
#include <string>
struct A {
int ax() const;
std::string ay( const std::string& jj ) const;
};
struct B {
A* f;
int bx() const;
std::string by( const std::string& jj ) const;
};
#endif // !DEVF_H
devf.cpp
#include "devf.h"
int A::ax() const {
return 5;
}
std::string A::ay( const std::string& jj ) const {
return jj;
}
int B::bx() const {
return f->ax();
}
std::string B::by( const std::string& ) const {
return f->ay( jj );
}
This should help from what you have shown.
I've tried it with this:
main.cpp
#include <iostream>
#include "devf.h"
int main() {
B b;
std::cout << b.bx() << std::endl;
std::cout << b.by( "hello world" ) << std::endl;
std::cout << "\nPress any key and enter to quit." << std::endl;
char q;
std::cin >> q;
return 0;
}
output
5
hello world
Press any key and enter to quit.
- EDIT
I asked the OP: Are you including other header files?
The OP answered with:
Yes, the header "devf.h" is included in other headers
And I believe this is where the OP's problem resides. I believe that the OP is a victim of Circular Includes which will result in multiple definitions.
Example:
A.h
#ifndef A_H
#define A_H
#include "B.h" // circular include
struct A {
int a;
B b;
};
#endif // !A_H
B.h
#ifndef B_H
#define B_H
#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
To resolve this circular include problem...
You need to use class or struct prototypes - forward declarations in the headers; works with pointer & reference types.
Only include other header files within a header file if the definition not the declaration is needed.
Once you have the class or struct's forward declaration in the header file
remove that class's include directive and put it within its cpp file
fixing the above example:
A.h
#ifndef A_H
#define A_H
// Since A has a pointer to B we remove the include from here
// and replace it with a forward declaration or class prototype...
// #include "b.h" // cicular include
class B;
struct A {
int a;
B b;
};
#endif // !A_H
A.cpp
#include "A.h"
#include "B.h" // moved the include to here - prevents circular includes
B.h
#ifndef B_H
#define B_H
// Since B does not require A we can omit this all together.
//#include "A.h" // circular include
struct B {
int b;
};
#endif // !B_H
B.cpp
#include "B.h"
You can refer to this Q & A Resolve build errors due to circular dependency amongst classes on stack for a more detailed explanation.
Once you go through the rest of your code base and fix all of the circular includes you should have no error as the above set of classes do compile and run without error.