I have two .cpp files in one project, main.cpp and myfile.cpp
I have globaly defined struct mystruct in main.cpp, now I want to use this struct in myfile.cpp.
When I write mystruct in a header file and include in both cpp files I get an error, saying mystruct redefinition. How should I solve this problem.
If you are trying to share the definition of a struct among several compilation units (cpp files), the common way is this: Place the definition of your struct in a header file (mystruct.h). If the struct contains any methods (i.e. it is rather a class with all member public by default), you can implement them in mystruct.CPP file, or, if they're lightweight, directly within the struct (which makes them inline by default).
mystruct.h:
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
struct MyStruct
{
int x;
void f1() { /* Implementation here. */ }
void f2(); /* Implemented in mystruct.cpp */
};
#endif
mystruct.cpp
#include "mystruct.h"
// Implementation of f2() goes here
void MyStruct::f2() { ... }
You can use your struct in as many cpp files as you like, simply #include mystruct.h:
main.cpp
#include "mystruct.h"
int main()
{
MyStruct myStruct;
myStruct.x = 1;
myStruct.f2();
// etc...
}
If, on the other hand, you are trying to share a global instance of the struct across several compilation units (it's not absolutely clear from your question), do as above but also add
extern MyStruct globalStruct;
to mystruct.h. This will announce that an instance is available with external linkage; in other words that a variable exists but is initialized elsewhere (in your case in mystruct.cpp). Add the initialization of the global instance to mystruct.cpp:
MyStruct globalStruct;
This is important. Without manually creating an instance of globalStruct, you'd get unresolved-external linker errors. Now you have access to globalStruct from each compilation unit that includes mystruct.h.
You should move the common struct to a header file and include that header in both files. Any other solution is a workaround.
The problem is that you basically have the same code twice as a result if you see an include as just a import of the code.
You can use #ifdef to fix it, see http://www.fredosaurus.com/notes-cpp/preprocessor/ifdef.html
Declaration and definitions are two different things. For your case, you are allocating space for your structure in main.cpp. In your header, you should use the extern modifier for your struct so that all files that include the header file will look in the global namespace for the structure. Hope it helps.
The standard C/C++ approach:
// source.h
Put all struct, class, typedef, macro definitions, extern variable declaraltions
// source.cpp
Implement the class, functions, define global/external variables
// main.cpp, and other parts of program
#include"source.h"
You should define structure in the header file only, you should remove definition from main.cpp
May be you can give more information about what is the layout of your project.
Going by the guess, probably your problem can be either of the two:
you want forward declaration of struct.
using include guards to prevent redefinition.
See the following link for how to handle both:
http://www.adp-gmbh.ch/cpp/forward_decl.html
The header files also use include guards, so you can figure out what exactly can solve your problem.
If you want to share any variable between multiple cpp files, you should declare it in header as extern. And without extern in one of that c++ files.
If you don't do it, it'll lack at linking, because multiple objects would have variable with same name. Instead when using extern one object would have this variable and other objects link it.
The header is where you declare what your struct will consist of (probably a common.h file included by main.cpp and myfile.cpp):
struct MyStruct {
int messageID;
int tempVariable;
};
In your main.cpp, this is where you actually use the struct:
void someFunction() {
struct MyStruct tempStruct;
// do something with it
tempStruct.messageID = 1;
}
Don't put the definition of your struct in both your main.h and main.cpp - or you will get a redefinition error!
Also, don't include the cpp file - include the header file (e.g. common.h). Without knowing more about the structure of your program, it is hard to provide better information.
Related
I think I'm doing something stupid, but I don't quite know what. I'm trying to rewrite a fairly simple library I have that is reading in some variables from a text file and then shares them with some other source files for use elsewhere. When I wanted to pass a double I was doing this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include <vector>
extern double coeff_A;
#endif
and then doing this in both the source file where it was defined and the other source files where I want to use it:
#include "SharedVariables.h"
to make coeff_A available in the new source file.
But then my model got more complicated and I was using more coefficients so I decided to store them in a structure and pass that structure using extern instead. I created a new header file for the structure (CParameters.h):
#pragma once
#if !defined(CParameters_h)
#define CParameters_h
typedef struct
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
} SGlobalParameterData;
#endif
and then defined the struct like this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include "CParameters.h"
#include <vector>
extern SGlobalParameterData globalParameters;
#endif
In the first source file where I read in all the values from the data files and using the values I've replaced:
#include "SharedVariables.h"
double coeff_A;
...
with
#include "SharedVariables.h"
SGlobalParameterData globalParameters;
globalParameters = readProperties(prefsFile);
....
In the second source file which also needs to use some of these variables I've added #include "SharedVariables.h" and then the IDE and compiler let me easily access globalParameters.coeff_A, globalParameters.coeff_B, etc.
I thought this should work and everything compiles without any errors, but it's not actually passing the values read into globalParameters to the second source file. Everything is just zero when I'm debugging the code.
So there are really two questions: 1) Is it possible to share structs using extern like for double, and 2) if it is, what have I done wrong.
Hopefully someone can point out my mistake.
Edit
I've added in an line of code in my example to show the function that assigns the values to the struct. This is working and the values read from the prefsFile are available and correct in the f1rst source file, but these values are not passed to source file 2. I'm going to do some more testing because it appears I may have made some other mistake elsewhere.
Your confusion stems from the use of typedef and mixing of declarations and definitions.
In C++ typedef isn't needed to define a struct type and is only confusing.
typedef struct { ... } SGlobalParameterData; - this declares a type SGlobalParameterData that is a struct. It defines no instance of the struct.
struct SGlobalParameterData { ... }; - same thing, declares a type SGlobalParameterData that is a struct.
struct { ... } globalParameterData; - this defines an object globalParameterData of an unnamed struct type.
struct SGlobalParameterData { ... } globalParameters; - this defines an object globalParameters of an struct type called SGlobalParameterData.
So... the following might be most readable/clean IMHO:
In the header:
struct SGlobalParameterData // type declaration
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
};
extern SGlobalParameterData globalParameters; // global instance *declaration*
In one of source files:
#include "the header above"
SGlobalParameterData globalParameters; // global instance *definition*
In other source files:
#include "the header above"
// globalParameters is already visible and usable
Of course you have to compile all source files and link them together into an executable.
Is it possible to share structs using extern like for double
Yes.
if it is, what have I done wrong.
Something that you haven't shown to us.
Everything is just zero
This is to be expected because variables with static storage are zero-initialised, and you never modify globalParameters in the example.
Here is your code running. Only change I made was to add some output, and actually set some other value than zero. That non-zero value works as expected: https://wandbox.org/permlink/CasO8c68W3FmBsQH
I am using boost msm library (you don't need to know how it works) to code my statemachine, and i have a cpp source file organization question.
in the first source file (1.cpp) I define the statemachine, the event and the actions and the transition table, but I would like to define the state in another cpp file just because I would need to edit the states much more often then anything else in the statemachine.
Now what I did is that I wrote the states in another source file (2.cpp) and I included 2.cpp in 1.cpp
It compiles and everything, but its not clean at all, Id like to encapsulate this somehow..Any ideas?
Well typically you would include only .h files, i.e., the header files that declare types and the functions that you will implement in your associated .cpp file. You should not need to include an implementation file at all. Have you created any header files? Here is a basic example:
// Foo.h
class Foo {
// note that it is not defined here, only declared
public void some_function(int i);
};
// Foo.cpp
#include "Foo.h"
#include <iostream>
// implement the function here
void Foo::some_func(int i) {
std::cout << i;
}
Typically in C++ the definitions of classes and the function prototypes exist in header files (ending in .h or .hpp), with the implementation of functions existing in source files (ending in .cpp or .cxx). This allows you to expose an external interface so that other files can use the definitions used in the first file. You would make function prototypes and class declarations in your header file, and then include that header file in both cpp files.
In general, it is good practice to only include header files, and not include source files in other files.
If i were to write this from scratch (a finite state machine),
i will put following inside:
fsm.h:
struct fsm_rule {
/* state to which this rule belongs to */
int state;
/* new state */
int next;
/* is called when rule matches */
int (*fn)(int in, void *ctx);
};
struct fsm_state {
int nrules;
struct fsm_rule *rules;
};
struct fsm {
int nstates;
struct fsm_state *states;
};
and then inside fsm.c i will go ahead and implement required methods.
PS: Ofcouse fsm.c includes fsm.h
I have two .c files and one .h file included from them both. In the .h file, I have declared global constants. When building with gcc, I get linking problems, telling me that the constants are defined twice, even though I have
#ifndef __FOO
#define __FOO
const struct foo bar = ...
#endif
I get
/tmp/ccql6KF1.o:(.rodata+0x0): multiple definition of `bar'
However, compiling the very same code with g++ works perfectly. Is there some differences in the way C and C++ treats global constants declared in .h files? What approach should I consider?
Please note that all objects need to share the memory for the constants, since I have limited resources.
You should declare the constant in a .h file and define it in a single .c file:
bar.h:
extern const struct foo bar;
bar.c:
#include "bar.h"
/* do this in a single file */
const struct foo bar = ...;
Then include bar.h everywhere you want to access bar:
something.c:
#include "bar.h"
void doSomethingWithBar() {
struct *foo something = &bar;
...
}
Edit (by Shahbaz): The reason why this works and your code doesn't work is that when you include a file, the contents of that file are copy pasted in place of #include (this is regardless of the file, you can include anything, including files with .h extension is just a convention). So when you say const struct foo bar; in a header file and include it in two files, it's exactly like writing that line in both files, therefore defining the variable in both files and hence the link error.
Your header protection also doesn't work (the
#ifndef __BAR_H__
#define __BAR_H__
... header contents
#endif
) because each of your source files are compiled separately, therefore when bar.h is included in one file and __BAR_H__ defined, when the next file is being compiled this definition of __BAR_H__ is lost.
You should declare only :
const struct foo bar;
and assign it a value in a .c file.
There are few global variables which are static in one of the header files. I see these variables are used in the associated .cc files. So, looks like this has no issues.
My questions are:
Whats the difference between including a global variable vs static global variable ?
I know static global doesnt have visibility outside its file. But dont know how this would work when it comes as part of a .h which is #included.
I wrote a sample program, and tried the same thing. But, I get compilation error the moment I make the variable static. When it is just global, it is fine.
So, is there something which I am missing on a regular g++ build ? (Please note, the initial case was on our official code base which has enough makefiles, .h files and all).
Thanks for the help !
Here is my sample program :
.h file:
#include <iostream>
typedef unsigned int uint;
static const int appk=189;
class abc1
{
public:
abc1(int x);
virtual void printVal();
};
.cc file:
#include "abc1.h"
extern int appk;
abc1::abc1(int x)
{
}
void abc1::printVal()
{
printf("abc1 print: %d\n", appk);
}
(1) If you put a global variable in a .h file and include it in various .cpp/.cc files then it will be defined multiple times for every file. So you are most like to get a linker error.
To overcome that, mostly you are likely to use extern keyword:
// myfile.h
extern int i;
and define that in only one translation unit:
// somefile.cc
int i;
(2) If you put a static global in a .h file and include it, then you will not get any error, because for every different translation unit, there will be a different copy for that static global variable.
// myfile.h
static int i; // creates a unique and unrelated copy in all .cc file where included
However, such usage is deprecated; instead of that it's better to use unnamed namespace:
namespace {
int i;
}
From your question, I don't see that you should get any linker error for static global.
Hard to tell your compilation error without code, but if you have a header that declares a static global, then you just create that global variable independently and separately in each translation unit that includes the header.
Example:
header.h:
#ifndef H_XXX
#define H_XXX
static int a;
#endif
file1.cpp:
#include "header.h"
// now have access to a variable called "a"
file2.cpp:
#include "header.h"
// now also have access to some "a"
The two files both have access to a global variable called a, but each file has its own separate copy, private to its translation unit, which is not visible outside.
For a practical example, I think cout is declared as a static global, so everyone who uses <iostream> gets their own copy.
static variable has internal-linkage. What it means is that if you have a static variable a in x.h and you include x.h in two files say m.cpp and n.pp then each of these two files gets its own copy of a which means if you change its value in m.cpp, then n.cpp is not going to see that change, because there exists two variables with same name in each translation unit (.cpp). And they're independent of each other.
But if a is not static, then including x.h in more than one files, you will get multiple-definition error, because each inclusion of x.h will try to define a, but since a is not static; it has external linkage now, which means if its defined in m.cpp, then you will get error when including x.h in n.cpp (or vice-versa). In this case, you've to write x.h as:
//x.h
extern int a;
And then define a in exactly one .cpp file, either m.cpp or n.cpp, but not both. Say its m.cpp.
//m.cpp
#include "x.h"
int a =10;
And you're done. Now you can include x.h in as many .cpp file as you want, and can access a, modify its value, do whatever you want. Any change to it, will be seen by all .cpp files now.
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.