Simple SFML/C++ question, confused about literal strings and static members - c++

I'm a bit confused by the code at http://www.sfml-dev.org/tutorials/1.6/graphics-sprite.php
Namely the code at the bottom detailing the class "Missile":
class Missile
{
public :
static bool Init(const std::string& ImageFile)
{
return Image.LoadFromFile(ImageFile);
}
Missile()
{
Sprite.SetImage(Image); // every sprite uses the same unique image
}
private :
static sf::Image Image; // shared by every instance
sf::Sprite Sprite; // one per instance
};
I am trying to use "Init" to load a file to the private image member of the class. I am trying to do this with:
if (!Missile::Init("missile.bmp")) return EXIT_FAILURE;\
then proceed to declare an object of that class. However, I am getting long, verbose errors that make me think that I should not be putting a string there, or that I am missing something fundamental. I'm a bit new to C++ so the syntax is still confusing me, I've looked at this for quite a while and can't figure it out. I've tried calling pointers, etc, but I really don't know what to do next.
Edit: The error I'm getting is:
main.o: In function Ship::Init(std::basic_string, std::allocator > const&):
main.cpp:(.text._ZN4Ship4InitERKSs[Ship::Init(std::basic_string, std::allocator > const&)]+0x10): undefined reference to Ship::Image
main.o: In function Ship::Ship():
main.cpp:(.text._ZN4ShipC2Ev[_ZN4ShipC5Ev]+0x19): undefined reference to Ship::Image

From the term, long verbose error, I am just guessing that you might have got confused with linker error. That's because, you might have either forgot to define,
static sf::Image Image;
in a .cpp file or forgot to link that .cpp file with your compilation where it's included.
Define your static member in appropriate .cpp file in global scope.
sf::Image Missile::Image;

Related

C++ undefined reference to enum type at linking time

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.

error: 'GenericEnclosure::GenericEnclosure' names the constructor, not the type

Whenever I build this code, I always get the "error: 'GenericEnclosure::GenericEnclosure' names the constructor, not the type".
I've already tried removing the GenericEnclosure:: with a new error then showing.
.cpp file
GenericEnclosure::GenericEnclosure frontLeftEnclosure{name, m_leftFrontDriveMotor, m_leftFrontTurnMotor, m_leftFrontTurnEncoder, 0.1};
.h file
class GenericEnclosure : public SwerveEnclosure {
public:
GenericEnclosure( std::string name,
frc::SpeedController& m_moveMotor,
frc::SpeedController& m_turnMotor,
rev::CANEncoder& m_encoder,
double m_gearRatio);
~GenericEnclosure();
From this, I would have hoped that it would build properly but there is something going on that I can't recognize. I still don't understand the source of the problem because I am new, so anything will be appreciated.
Edit: I was right to remove the GenericEnclosure:: but I now get this error
undefined reference to `GenericEnclosure::GenericEnclosure(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, frc::SpeedController&, frc::SpeedController&, rev::CANEncoder&, double)'
The way how you should write the definition of GenericEnclosure's constructor:
GenericEnclosure::GenericEnclosure(std::string name,
frc::SpeedController& m_moveMotor,
frc::SpeedController& m_turnMotor,
rev::CANEncoder& m_encoder,
double m_gearRatio)
{
// something goes here
}
The way how you should declare a variable of type GenericEnclosure:
GenericEnclosure frontLeftEnclosure{name, m_leftFrontDriveMotor, m_leftFrontTurnMotor, m_leftFrontTurnEncoder, 0.1};
So GenericEnclosure::GenericEnclosure tells, that you declare a variable of type GenericEnclosure in namespace GenericEnclosure, but it seems it isn't so.
UPD If you haven't defined the constructor (and all the declared methods), you can't declare a variable, your second error tells about it.

Problem using static variable in a static function

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.

undefined reference error due to use of static variables [duplicate]

This question already has answers here:
static variable link error [duplicate]
(2 answers)
Closed 8 years ago.
I asked a question earlier today about singletons, and I'm having some difficulties understanding some errors I encountered. I have the following code:
Timing.h
class Timing {
public:
static Timing *GetInstance();
private:
Timing();
static Timing *_singleInstance;
};
Timing.cpp
#include "Timing.h"
static Timing *Timing::GetInstance() { //the first error
if (!_singleInstance) {
_singleInstance = new Timing(); //the second error
}
return _singleInstance;
}
There are two errors in this code which I can't figure out.
The method GetInstance() is declared in the header as static. Why in the cpp file do I have to omit the word static? It gives the error: "cannot declare member function ‘static Timing* Timing::GetInstance()’ to have static linkage". The correct way to write it is:
Timing *Timing::GetInstance() { ... }
Why can't I write _singleInstance = new Timing();? It gives the error: "undefined reference to Timing::_singleInstance". I solved this error by defining _singleInstance as a global var in the cpp file.
1: static means "local linkage" when used for a function declaration/definition outside a class-declaration.
Local linkage means that the particular function can only be referenced from code inside this particular file, and that doesn't make much sense with a method in a class.
2: Since your class declaration can be included multiple times, the actual storage for the static member should be defined in the cpp-file:
#include "Timing.h"
Timing* Timing::_singleInstance;
Timing *Timing::GetInstance() { //the first error
if (!_singleInstance) {
_singleInstance = new Timing(); //the second error
}
return _singleInstance;
}
Referencing to question 2: You need to specify the static variable at the top of your cpp-file:
Timing* Timing::_singleInstance = NULL;
static within a class means something completely different than static outside of it. Yeah, not the greatest design decision of C++, but, we have to live with it.
I imagine the whining comes from the linker, and it's because you have declared that variable but never defined it, making it an undefined references. Just add in your .cpp file a line like:
Timing* Timing::_singleInstance;
yes, you have to omit the static in the .cpp file
You'll have to 'reserve memory' for _singleInstance somewhere, e.g. by writing the following in the .cpp file:
Timing *Timing::_singleInstance = NULL;
(outside the definition of the member functions)
In the definition, you need to omit the static keyword. Its because that's teh syntax of C++. Nothing big.
Once you fix error number 1, error number 2 will be fixed automatically.

GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'

I'm setting up a C++ project, on Ubuntu x64, using Eclipse-CDT. I'm basically doing a hello world and linking to a commerical 3rd party library.
I've included the header files, linked to their libraries, but I still get linker errors. Are there some possible problems here other than the obvious (e.g. I am 99% sure I'm linking to the correct library).
Is there a way to confirm the static libraries I am linking to are 64bit?
Is there a way to confirm that the library has the class (and methods) I am expecting it to have?
Eclipse says:
Building target: LinkProblem
Invoking: GCC C++ Linker
g++ -L/home/notroot/workspace/somelib-3/somelib/target/bin -o"LinkProblem" ./src/LinkProblem.o -lsomelib1 -lpthread -lsomelib2 -lsomelib3
./src/LinkProblem.o: In function `main':
/home/notroot/workspace/LinkProblem/Debug/../src/LinkProblem.cpp:17: undefined reference to `SomeClass::close()'
./src/LinkProblem.o: In function `SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `SomeClass::SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:148: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:151: undefined reference to `SomeClass::~SomeClass()'
./src/LinkProblem.o: In function `~SomeOtherClass':
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `vtable for SomeOtherClass'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
/home/notroot/workspace/somelib-3/somelib/include/sql/somefile.h:140: undefined reference to `SomeClass::~SomeClass()'
collect2: ld returned 1 exit status
make: *** [LinkProblem] Error 1
This linker error usually (in my experience) means that you've overridden a virtual function in a child class with a declaration, but haven't given a definition for the method. For example:
class Base
{
virtual void f() = 0;
}
class Derived : public Base
{
void f();
}
But you haven't given the definition of f. When you use the class, you get the linker error. Much like a normal linker error, it's because the compiler knew what you were talking about, but the linker couldn't find the definition. It's just got a very difficult to understand message.
Assuming those methods are in one of the libs it looks like an ordering problem.
When linking libraries into an executable they are done in the order they are declared.
Also the linker will only take the methods/functions required to resolve currently outstanding dependencies. If a subsequent library then uses methods/functions that were not originally required by the objects you will have missing dependencies.
How it works:
Take all the object files and combine them into an executable
Resolve any dependencies among object files.
For-each library in order:
Check unresolved dependencies and see if the lib resolves them.
If so load required part into the executable.
Example:
Objects requires:
Open
Close
BatchRead
BatchWrite
Lib 1 provides:
Open
Close
read
write
Lib 2 provides
BatchRead (but uses lib1:read)
BatchWrite (but uses lib1:write)
If linked like this:
gcc -o plop plop.o -l1 -l2
Then the linker will fail to resolve the read and write symbols.
But if I link the application like this:
gcc -o plop plop.o -l2 -l1
Then it will link correctly. As l2 resolves the BatchRead and BatchWrite dependencies but also adds two new ones (read and write). When we link with l1 next all four dependencies are resolved.
Qt C++ will show this error when you change a class such that it now inherits from QObject (ie so that it can now use signals/slots). Running qmake -r will call moc and fix this problem.
If you are working with others via some sort of version control, you will want to make some change to your .pro file (ie add/remove a blank line). When everyone else gets your changes and runs make, make will see that the .pro file has changed and automatically run qmake. This will save your teammates from repeating your frustration.
The problem for me turned out to be pretty obscure. My class looked like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() { }
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
//-----------------------------------------
//-----------------------------------------
// main.h
class derived : public base {
public:
virtual int foo() ;
};
//-----------------------------------------
//-----------------------------------------
// main.cpp
int main () {
derived d;
}
//-----------------------------------------
The problem is in the linker. My header file went in a library somewhere, but all the virtual functions were declared 'inline' in the class declaration. Since there was no code using the virtual functions (yet), the compiler or linker neglected to put actual function bodies in place. It also failed to create the vtable.
In my main code where I derived from this class, the linker tried to connect my class to the base class and his vtable. But the vtable had been discarded.
The solution was to declare at least one of the virtual functions' bodies outside the class declaration, like this:
//-----------------------------------------
// libbase.h
class base {
public:
base() { }
virtual ~base() ; //-- No longer declared 'inline'
virtual int foo() { return 0; }
};
//-----------------------------------------
//-----------------------------------------
// libbase.cpp
#include "libbase.h"
base::~base()
{
}
//-----------------------------------------
In regards to problems with Qt4, I couldn't use the qmake moc option mentioned above. But that wasn't the problem anyway. I had the following code in the class definition:
class ScreenWidget : public QGLWidget
{
Q_OBJECT // must include this if you use Qt signals/slots
...
};
I had to remove the line "Q_OBJECT" because I had no signals or slots defined.
I had this error message. The problem was that I declared a virtual destructor in the header file, but the virtual functions' body was actually not implemented.
This error will also occur when we simply declare a virtual function without any definition in the base class.
For example:
class Base
{
virtual void method1(); // throws undefined reference error.
}
Change the above declaration to the below one, it will work fine.
class Base
{
virtual void method1()
{
}
}
In my case the problem occured when i forgot to add the =0 on one function in my pure virtual class. It was fixed when the =0 was added. The same as for Frank above.
class ISettings
{
public:
virtual ~ISettings() {};
virtual void OKFunction() =0;
virtual void ProblemFunction(); // missing =0
};
class Settings : ISettings
{
virtual ~Settings() {};
void OKFunction();
void ProblemFunction();
};
void Settings::OKFunction()
{
//stuff
}
void Settings::ProblemFunction()
{
//stuff
}
I stumbled across the issue now, too. The application defined a pure virtual interface class and a user-defined class provided through a shared lib was supposed to implement the interface. When linking the application, the linker complained that the shared lib would not provide vtable and type_info for the base class, nor could they be found anywhere else.
Turned out that I simply forgot to make one of the interface's methods pure virtual (i.e. omitted the " = 0" at the end of the declaration. Very rudimentary, still easy to overlook and puzzling if you can't connect the linker diagnostic to the root cause.
I had this error message when trying "hello world" like things with Qt. The problems went away by correctly running the qt moc (meta object compiler) and compiling+including these moc-generated files correctly.
If you have a base class with pure virtual function, make sure your base class constructor and destructor has body otherwise linker fails.
I put this for future visitors:
if you are receiving the error on creating an Exception object, then the cause of it probably is a lack of definition for what() virtual function.