所以我的第一个问题是为什么作者在这里使用前向声明?
这样编译器在遇到GameCharacter
该行时就知道这是一个有效的名称int defaultHealthCalc(const GameCharacter& gc);
。
而我的第二个问题是如何理解 typedef 声明以及如何使用它?
理想情况下,您不再使用它。
从 C++11 开始,using
是更好的选择,因为它更具可读性;与typedef
'ed 函数指针不同,它清楚地将名称与名称所描述的分开。比较一下:
typedef int (*HealthCalcFunc)(const GameCharacter&);
有了这个:
using HealthCalcFunc = int (*)(const GameCharacter&);
在该typedef
版本中,名称HealthCalcFunc
的两侧都围绕着名称所描述的内容。这会损害可读性。
但是代码仍然可以改进,因为 C++11 还引入了std::function
作为函数指针上方的替代和/或抽象层。
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
这太可读了,几乎不需要解释。HealthCalcFunc
是一个返回 anint
并接受 a的函数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));
}
另请参阅我应该在 C++ 中使用 std::function 还是函数指针?.