i have a full static class, using a std::map
thats the simplified case
.h
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <map>
class Keyboad {
static std::map<char, bool> pressed;
static void keyPressedEvent(char _key);
};
#endif
.cpp
#include "Keyboard.h"
void Keyboard :: keyPressedEvent(char _key) {
Keyboard :: pressed[_key] = true;
}
but there is a problem with the static member variable, because i get
Undefined symbols:
"Keyboard::pressed", referenced from:
__ZN15Keyboard7pressedE$non_lazy_ptr in Keyboard.o
(maybe you meant: __ZN15Keyboard7pressedE$non_lazy_ptr)
ld: symbol(s) not found
collect2: ld returned 1 exit status
when i remove it, it runs ok
why do i get this problem, there should be no problem when using a static variable :/
thanks
You need to define the pressed map in your .cpp file:
#include "Keyboard.h"
std::map<char, bool> Keyboard::pressed;
// The rest as before
You should add this to .cpp file
std::map<char, bool> Keyboad::pressed;
Consider static class members as global variables. Compiler should allocate memory for them inside of the only object file. So you should define them in corresponding source file.
A static member in the class definition is just a declaration. You
still have to provide the definition, exactly like you did for the
function. Just add
std::map<char, bool> Keyboard::pressed;
in a source file somewhere. (For mapping chars, you might also
consider a simple
bool Keyboard::pressed[256];
, indexed with the char converted to unsigned char.)
Consider a simpler case. A global variable counter is declared in multiple header files:
int counter; // This appears in 3 HEADER files.
Few source files do refer it. When you compile and link it, compiler would emit linker error saying that counter is already defined in some set of .OBJ files (Error message is dependent on compiler).
To solve this, you just put extern in front of variable (in all header files):
extern int counter; // This appears in 3 HEADER files.
And when you rebuild it, linker will complain that counter is not defined anywhere.
To solve this issue, you define this variable in one source file (any one):
int counter;
And it resolves the issue.
The static-variable of class is nothing but a global variable, which can be accessed by classname::variablename format. The accessibility is same - global.
Related
This is my first time encountering this type of linking error for 20 years while trying to use other people's code.
Here I will be brief and using abbreviated examples.
Say the file enums.hpp
==== content====
#ifndef _BLABLA_
#define _BLABLA_
enum SomeKind { BLACK, RED, GREEN }
static void parse(const std::string& s, SomeKind) {
// definition
}
..... More enum, and static functions
#endif
In this file there are several enum and parse. Because of the STATIC keyword, the compiler will complain about the unused functions. I experimented by moving the definition of those function to a enum.cpp file. Then at link time, I am getting the error message:
undefined reference to `someNameSpace::SomeKind
One solution I will try to use the library as is (I will probably do that). This project (I am using) is a CMake project. What's a better way of organizing the original code to git rid of both problems: unused function, and undefined reference?
After removing the static label then it get rid of the linking problem of the enum. Essentially the new organization is as:
enums.hpp
enum SomeKind { }
void someFunction(SomeKind sk);
enums.cpp
void someFunction(SomeKind sk) {
// definition here
}
I think elimination of the static make the function visible and some how included in the linking stage. This is a big library, I have only a few hours looking into this library.
This is an Arduino project compiled in Visual Studio (using visual micro plugin). I am getting the following error:
AutonomyHandler.cpp.o (symbol from plugin): In function AutonomyHandler::setup() const
(.text+0x0): multiple definition of Module::AvailableCommandKeys
ArduinoProject.cpp.o (symbol from plugin)*: (.text+0x0): first defined here
I am using an enum of CmdKeys within the class definition, and I can use the line of code below to get the available set of keys, but when I try to use it, I get multiple compile errors as seen above for each place I have used it.
Module::AvailableCommandKeys
My Module.h looks as follows:
#ifndef _MODULE_h
#define _MODULE_h
class Module {
public:
enum CmdKeys { Forward, Left, Back, Right, Stop };
static const CmdKeys AvailableCommandKeys[2];
// other definitions...
};
const Module::CmdKeys Module::AvailableCommandKeys[] = { Forward, Back };
#endif
Does anyone know what is happening? I have had this issue before and making the members non-static fixed the issue but I want to keep these enum arrays static.
Since writing this post I found the answer so I thought I would post to help others anyway.
To fix the issue, you just need to move the initialisation of the static members from the definition file (.h) to the declaration file (.cpp)
Module.h looks as follows:
#ifndef _MODULE_h
#define _MODULE_h
class Module {
public:
enum CmdKeys { Forward, Left, Back, Right, Stop };
static const CmdKeys AvailableCommandKeys[2];
// other definitions...
}
const Module::CmdKeys Module::AvailableCommandKeys[] = { Forward, Back };
#endif
Module.cpp looks as follows:
#include "Module.h"
const Module::CmdKeys Module::AvailableCommandKeys[] = { Forward, Back };
// Other code...
Place the line:
const Module::CmdKeys Module::AvailableCommandKeys[] = { Forward, Back };
in a .cpp file.
Main idea:
I wrote a piece of code for dijkstra's algorithm and I'm dandy. However, I need to call the function (from a header file) in other codes and stuff. But I need to store the variables only when the function is called (so once the function is called it will return variables but won't return variable from previous calls). And I need to reference these variables other codes/files.
How I'm storing variables:
a structure that contains two vector.
My question:
Would it be best to create a .h file to store a structure and just change the variables there or is there a way to call variable from another function in another file and use it without having to worry about memory issues and whatnot?
Also... how would I set up my .h file for this dijkstra algorithm if my my int main takes no arguments?......
-Edit-
typedef struct
{
int a;
int b;
} STR;
STR Func()
{
STR str;
str.a = 5;
str.b = 6;
return str;
}
Basic model of my code. But I need to reference the structure and it's variable in another file with another function. However I get undefined reference to 'main' error when compiling so I added an int main() that calls Func(). Suggestions?
-edit dos-
Proposed fix
.h should include:
struct_name dijkstra(input variables)
.cpp should include:
#include "dijkstra.h"
typedef struct{
blah...
}struct_name;
struct_name dijkstra{
struct_name retval;
function def...
return retval;
}
main.cpp should include:
#include "dijkstra.h"
#include "dijkstra.cpp"
int main(){
initialize variables... blah
struct_name return_struct = dijkstra(input variables);
return 0;
}
Usually you would pass in all the input data the algorithm needs as input parameters, and return all the useful output data the algorithm creats as a return type. You could create a separate C++ struct or class if you need to bundle a few pieces of information together.
For data structures used internally by the algorithm - you would usually declare them only in the .cpp file, not the .h file. So, the user will not have any access / visibility of the internals (which is useful if you want to change how it works later).
So, the header file should just have the function declaration - with input arguments and output return type. All the algorithm code goes into the .cpp file, which includes the .h file. The header file is the 'interface' and the cpp file is the 'implementation', which we try to keep separate.
EDIT : (summarizing useful points from subsequent discussion)
This tutorial shows how the 2 .cpp files and one .h file fit together. Basically both .cpp files include the .h file. The .h file includes the declarations (for both the function type and for the struct type) but not the function definition :
www.learncpp.com/cpp-tutorial/19-header-files/
Since you are using g++, you can compile them into a single executable using :
g++ -o executable_name main.cpp dijkstra.cpp
(i have edited my original question to make it more understandable)
here is the prototype for the problem ....
//Txn.h ---this has a static variable, usable by the pgms including it.
class Txn
{
public:
static int i;
static void incr_int();
};
Txn::i=0;
//Txn.cpp
void Txn::incr_int() {i++;}
->produce LibTxn.so
//class1.cpp -> one of the pgm using the static var from Txn.h
#include Txn.h
Txn::incr_int()
-> produce class1.o, with LibTxn.so.
// class2.cpp ->another pgm using the static var from Txn.h
#include Txn.h
cout<<"Txn::i;
-> produce class2.o, by including LibTxn.so
-> .produce class3 (an exe) by using class1.o,class2.o. Since, both class1 and 2 has the statement "Txn::i=0" from "Txn.h", multiple declaration issue happens.
-> .If I remove the statement "Txn::i=0" from Txn.h, then "undefined reference" error appears.
-> .At high lvl, this problem is a kind of having a session variable, which should be assessible from any func in a exe. Those func can be in any obj files used to form the exe. I am fine for any sol, even without static. But I can't change the creation of different .o files (which are using this session var) and combining the .o to produce the exe.
It is hard to figure out exactly what the problem is if you cannot provide the real code, or at least an example which has the same problem as the real code.
However, most likely the root cause of the problem is that you are not only declaring, but also defining your class's static variable in the header file that contains the class definition.
This means that all the translation units (i.e. .cpp files) which include that header will contain a definition for the static variable, and when merging all the corresponding object files, the linker will eventually complain about that symbol being defined multiple times.
If this is the case, what you should do is to take the initialization of the static variable out of the header file which contains your class's definition and put it in one (and only one) .cpp file.
I tried to recreate the problem as you described, but it compiled just fine on my computer, and it is difficult to go further without seeing your code.
In the code below, the header tells (declares) every .cpp file that includes it about Foo::x, but Foo::x lives in (is defined in) Foo.cpp (and Foo.o)
foo.h:
class Foo {
public:
static int x;
};
Foo.cpp:
#include "foo.h"
int Foo::x;
main.cpp:
#include <iostream>
#include "foo.h"
int main(int argc, char *argv[]) {
Foo::x = 42;
std::cout << "Foo::x is " << Foo::x;
}
Yes. it worked by defining the static variable in .cpp.
Special thanks to Andy Prowl and iWerner.
My goal is to have global constants in a C++ game I'm working on (to represent some graphics info and the like). My current implementation is to toss them all in a .h and include them everywhere. This works, except that every time I change a setting, the entire code base must be recompiled.
So, my next idea was to toss them in some configuration txt file and parse them in, that way no code is actually changed when settings change. The parser was simple enough, and I could put the values into the constants, but because the parser was a code block, the constants were no longer global.
Is there a good way to solve this? Perhaps some way to make them global despite being in a block or some way to avoid recompiling everything when changing settings?
The way I used solve this is to put the variables in a separate global namespace, which is in a header file named something like config.h, then include that file everywhere.
// In config.h
#ifndef CONFIG_H
#define CONFIG_H
namespace config
{
extern int some_config_int;
extern std::string some_config_string;
bool load_config_file();
}
#endif
Then in a source file, you define the variable and also set them to a default value. This source file also have the code to load the variables from your configuration file.
// In config.cpp
namespace config
{
int some_config_int = 123;
std::string some_config_string = "foo";
}
bool config::load_config_file()
{
// Code to load and set the configuration variables
}
Now in every source file you need the configuration variables, include config.h and access them like config::some_config_int.
However, there is no "proper" way of solving this, all ways that work are proper in my eyes.
Another way to do this would be to create a singleton class.
#include <fstream>
#include <map>
#include <string>
class ConfigStore
{
public:
static ConfigStore& get()
{
static ConfigStore instance;
return instance;
}
void parseFile(std::ifstream& inStream);
template<typename _T>
_T getValue(std::string key);
private:
ConfigStore(){};
ConfigStore(const ConfigStore&);
ConfigStore& operator=(const ConfigStore&);
std::map<std::string,std::string> storedConfig;
};
Here the configuration is saved in a map, meaning as long as parseFile can read the file and getValue can parse the type there is no need to recompile the config class if you add new keys.
Usage:
std::ifstream input("somefile.txt");
ConfigStore::get().parseFile(input);
std::cout<<ConfigStore::get().getValue<std::string>(std::string("thing"))<<std::endl;
What about creating functions that return your constants that you can specify in a .cxx file? For example:
// foo.h
const int BAR();
// foo.cxx
const int BAR() {
return 10;
};
put only the declarations in head file and put the definitions in a cpp file. then you change the definitions in cpp file will not cause all code recompiled