Итак, мой первый вопрос: почему автор использует здесь предварительную декларацию?
Чтобы компилятор знал, что GameCharacter
является допустимым именем, когда встречается строка int defaultHealthCalc(const GameCharacter& gc);
.
И мой второй вопрос: как понимать объявление typedef и как его использовать?
В идеале вы не его больше не используете.
Начиная с C++11, using
является лучшей альтернативой, поскольку она более удобочитаема; в отличие от указателей на функции typedef
, он четко отделяет имя от того, что это имя описывает. Сравните это:
typedef int (*HealthCalcFunc)(const GameCharacter&);
С этим:
using HealthCalcFunc = int (*)(const GameCharacter&);
В версии typedef
имя HealthCalcFunc
окружено с обеих сторон тем, что описывает имя. Это вредит читабельности.
Но код все еще можно улучшить, потому что C++11 также представил std::function
в качестве альтернативы и/или уровня абстракции над указателями функций.
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
Это настолько читабельно, что даже объяснять не нужно. HealthCalcFunc
— это функция, которая возвращает int
и принимает const GameCharacter&
.
Функция defaultHealthCalc
подходит под это определение. Вот полный пример:
#include <functional>
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter {
public:
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{return healthFunc(*this); }
private:
HealthCalcFunc healthFunc;
};
Самое замечательное в std::function
то, что вы не ограничены отдельными функциями. Вы можете передать любую функциональную вещь. Вот некоторые примеры:
struct Functor
{
int f(const GameCharacter& gc);
};
int main()
{
// normal function:
GameCharacter character1(defaultHealthCalc);
// lambda:
GameCharacter character2([](auto const& gc) { return 123; });
// using std::bind:
Functor functor;
using namespace std::placeholders;
GameCharacter character3(std::bind(&Functor::f, functor, _1));
}
См. также Должен ли я использовать std::function или функцию указатель в C++?.
person
Christian Hackl
schedule
12.03.2017