Reputation: 49
I have a header which defines some functions I need. I include them in two files which are themselves included in main.cpp, but I get the multiple definitions of function error, despite the fact that I put
#ifndef MYFUNCTION_H
#define MYFUNCTION_H
//code
#endif
in my code. So what did I do wrong? Here is my header:
#ifndef EXTRASFMLFUNCTIONS_H
#define EXTRASFMLFUNCTIONS_H
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Text.hpp>
inline void setCenterPos(sf::Sprite &entity, const sf::Vector2f& position)
{
entity.setPosition(sf::Vector2f{(position.x - entity.getGlobalBounds().width / 2), position.y - (entity.getGlobalBounds().height / 2)});
}
inline void setCenterPos(sf::Text &entity, const sf::Vector2f& position)
{
entity.setPosition(sf::Vector2f{(position.x - entity.getGlobalBounds().width / 2), position.y - (entity.getGlobalBounds().height / 2)});
}
inline sf::Vector2f getCenter(const sf::Sprite& entity)
{
return sf::Vector2f{entity.getGlobalBounds().width / 2, entity.getGlobalBounds().height / 2} + entity.getPosition();
}
inline void scaleTo(sf::Sprite& entity, const sf::Vector2f& size)
{
entity.scale(size.x / entity.getGlobalBounds().width, size.y / entity.getGlobalBounds().height);
return;
}
inline void scaleToWidth(sf::Sprite& entity, const float &width)
{
entity.scale(width / entity.getGlobalBounds().width, width / entity.getGlobalBounds().width);
return;
}
inline void scaleToHeight(sf::Sprite& entity, const float &height)
{
entity.scale(height / entity.getGlobalBounds().height, height / entity.getGlobalBounds().height);
return;
}
#endif
Edit: it works with the inline keyword
Upvotes: 2
Views: 187
Reputation: 6484
In C++, the One Definition Rule (ODR) states that objects and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit. As cppreference states under One Definition Rule:
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
That's why you get multiple definition link errors when you do not inline the functions. The functions are included (literally copied) into the implementation files. The header guards do not prevent this since the files are included separately. So you violate ODR because the same function with external linkage is defined multiple times.
When you inline the functions, then each translation unit (implementation file + all its include files) gets its own copy of the function, i.e. it has internal linkage. As long as the inline function has the same definition in each translation unit, it is okay - there is no violation of the ODR.
You have two options:
I would go with the first option since the functions are short and not so complicated.
Upvotes: 3
Reputation: 49
One year later, I learnt that the inline keyword has lost its original meaning. It used to be used to act like a preprocessing instruction, kind of, and copy paste the function wherever it was called instead of doing a jump instruction with all the function calls stuff that goes on. It's a little bit faster if you call your function 1 million times, but obviously, the compilators do it by themselves now. What inline means now is 'yeah, this thing can be defined multiple times, it's alright'.
Upvotes: 0