Calling non-inline functions from inline functions - c++

In a library, I have the following in a header:
// button.hpp
class ExtraButtons
{
public:
static inline void show() { setShown(true); }
static inline void hide() { setShown(false); }
static void setShown(bool shown);
};
and the following in a source file:
#include "button.hpp"
void ExtraButtons::setShown(bool shown)
{
}
The library compiles fine. However, when I'm using the library and I include button.hpp, I get this error from the setShown calls in show() and hide():
undefined reference to `ExtraButtons::setShown(bool)'
I can fix the problem by removing the inline from show() and hide() and defining them in the source file, like normal, OR by making setShown inline as well. Why is this the case? Are these the only solutions?

It looks like either you aren't linking the library binary into your project, or your actual definition for setShown is inline void ExtraButtons::setShown(bool shown) (note that it's accidentally marked inline in the source file).

Related

Unexpected Visual C++ linker behavior regarding function exports, when an inline function is involved

We build a static library with Visual C++ (version 15 is used), and this library that has the following functions:
extern "C" void __stdcall Internal()
{
...
}
class SomeClass {
inline void SomeFunc()
{
Internal(); // calling Internal here
}
}
When this static library is linked to an EXE, Internal gets exported from the EXE (i.e., one can see Internal in the EXE's exports). If we make SomeFunc not inline, Internal doesn't get exported.
Does anybody know why the "inline" modifier has an effect of an undesired export being generated?

Cocos2D-X Linker Error; what am I missing?

I'm following a Cocos2D-X tutorial for iOS on XCode 5 and the instructor started off by creating a bunch of classes and header files. Among those is a header file called "Utils.h" that contains some static functions
class Utils
{
public:
static Game* gameLayer();
static HUD* hudLayer();
static cocos2d::CCLayer* layerWithTag(int tag);
static cocos2d::CCSize s();
static cocos2d::CCAnimate* getAnimationWithFrames(int from, int to);
static void scaleSprite(cocos2d::CCSprite * sprite);
static float getScale();
static void setScale(float s);
static float getArtScaleFactor();
static void setArtScaleFactor(int s);
};
The s() functions is defined in Utils.cpp to just return CCDirector::sharedDirector()->getWinSize();
Now, the problem is: when the s() function is called in my main menu scene (Utils::s().width for instance), I get this error "Linker command failed with exit code 1 (use -v to see invocation)" and "Symbol(s) not found for architecture i386". However, when I deleted the s() function definition from Utils.cpp and just added the function in the class in the header file so that it becomes
//Utils.h
class Utils
{
public:
.......
static cocos2d::CCSize s()
{
return CCDirector::sharedDirector()->getWinSize();
}
......
It compiles without an error...
Why is it that I get this error when the function is in the cpp file instead of the header file? I know my problem is already solved but it's just driving me crazy
Thanks! :)
Edit: I thought this was a given but to be clearer, in the main menu scene I included Utils.h not Utils.cpp
Please note that such errors also appear when you have declared a function in one file (say Cpp) and not in the .h file.
Most common reason that i have seen is because one declares a function in the .h file but forget to give the implementation.

Undefined reference error C++

i accessed a static function(funA()) in class A (all function in this class is static) but getting Undefined reference error. I included header
Please help.
// H file
Class A
{
static void funA();
};
// Cpp file
void A::funA() { }
Accessed in class B
void B::funB()
{
A::funA()
}
Make sure you have something like this on your header:
// a.h
class A {
static void funA();
};
// a.cpp
void
A::funA() {
// do something on your function
}
From your edit it seems you're missing the public: part before static void FunA().. did you just forget to edit it in or maybe it's really missing in your .cpp?
Have you included the right .lib file, if necessary?
You should always initizalize static functions and variables in cpp file before using
Is it possible that you have double declaration in your code, because this would give you a compiler error.

Symbol not found linking a library

I'm writing a simple game engine, and I have the EntityComponent.h file:
#ifndef Psycho2D_Core_EntityComponent_
#define Psycho2D_Core_EntityComponent_
#include <string>
namespace psycho2d{
class EntityComponent{
private:
std::string m_name;
public:
EntityComponent(const std::string &name);
virtual ~EntityComponent();
const std::string& getName() const;
virtual void initialize() = 0;
virtual void loadProperties() = 0;
virtual void update() = 0;
virtual void destroy() = 0;
};
}
#endif
And the relative EntityComponent.cpp file:
#include "EntityComponent.h"
#include <string>
psycho2d::EntityComponent::EntityComponent(const std::string &name){
this->m_name = name;
}
psycho2d::EntityComponent::~EntityComponent(){}
inline const std::string& psycho2d::EntityComponent::getName() const{
return this->m_name;
}
These two file are part of a framework (I'm working on a Mac). They compile well.
The problem is when I write an executable that use the library.
I have created a sub-class of EntityComponent, and it compiles. But, if I call the getName() function, the linker tell me:
"psycho2d::EntityComponent::getName() const", referenced from:
_main in main.o
Symbol(s) not found
Collect2: ld returned 1 exit status
What I can do?
Thanks.
Put the code for the inline function in the header file, if you want to reference it from multiple .cpp files.
Reference here.
An external linkage inline function must defined (as effectively the same) in every translation unit where it's used.
So either remove the inline from the definition, or place the definition in the header file.
Cheers & hth.,
Your (slightly modified to include a subclass to text) code compiles fine on my machine (A Mac, too. GCC 4.2.1)
Try removing all .o-files and compile with a clean directory. If that fails too, I'd try to remove the inline-definition.
Try removing the inline qualifier from your implementation.

In .cpp file, defining methods with "class Foo { void method() {} };" instead of "void Foo::method() {}"?

When you have inline definitions of functions in the header file, and you want to move the the function definition bodies out of the header and into a .cpp file, you can't just cut-and-paste the functions as they were defined in the header; you have to convert the syntax from this:
class Foo
{
void method1() { definition(); }
void method2() { definition(); }
void method3() { definition(); }
};
To this:
void Foo::method1() { definition(); }
void Foo::method2() { definition(); }
void Foo::method3() { definition(); }
Edit: Just wanted to point out that what I'm hoping to avoid is having to type the class name in front of every method name. It may seem like a small thing but when you're moving a lot of function definitions out of the header and into the cpp file, it adds up. And when the return type is especially complicated, you have to find where in the line each return type ends and each method name begins.
So my question is, do I have to do it like that second block of code above? What if I did this (is the following standards compliant C++?):
In Foo.h:
class Foo
{
void method1();
void method2();
void method3();
};
In Foo.cpp:
#include "Foo.hpp"
class Foo
{
void method1() { definition(); }
void method2() { definition(); }
void method3() { definition(); }
};
This will not work: the compiler will see this as you redefining the class. I'm afraid there is no way around this, it's part of the language.
[ps: I know these kinds of jobs are tedious, but we all have to do them at one time or another. If it is that big a job, you could look at writing a script to do it for you, but it really would have to be a big job to justify the effort imho, parsing C++ is not fun]
No. I believe that this violates the One Definition Rule. In any case, it isn't allowed. Remember that #include isn't really seen by the compiler proper. The include is processed before the source is fed to the compiler so what the compiler sees is something like:
#line "foo.cpp" 1
#line "foo.h" 1
class Foo {
void method1();
...
};
#line "foo.cpp" 3
class Foo {
void method1() {...}
};
So it looks like two conflicting definitions of the same symbol.
yes you have to do it as you show at the top (your original code), I don't think there's a lazy way around it.
You can put the class name in the original definition. That always works. Unfortunately for inlining you will usually no longer really get inlined if it gets put into the cpp file unless it's very very simple or you use a compiler directive.
If it's large enough to want to move into cpp most of the time you don't want it inlined, though.
Another thing is to consider 'helper' classes. Define those elsewhere, which do a lot of the implementation details. Then you can call that in the derived class and it will be inlined.