Lix*_*Bai 4 c++ typedef forward-declaration effective-c++
最近,我读了有效C++这本书,第35项中有关于typedef的声明使我感到困惑.
class GameCharacter; // Question1: Why use forward declaration?
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter{
public:
typedef int (*HealthCalcFunc)(const GameCharacter&); // Question 2: What does this mean?
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{}
int healthValue() const
{return healthFunc(*this); }
private:
HealthCalcFunc healthFunc;
};
Run Code Online (Sandbox Code Playgroud)
所以我的第一个问题是:为什么作者在这里使用前瞻性声明?有什么具体原因吗?
我的第二个问题是:我如何理解typedef声明,以及如何使用它?我只知道类似的东西typedef int MyInt;
son*_*yao 13
所以我的第一个问题是为什么作者在这里使用前向声明?
由于函数的声明defaultHealthCalc使用const GameCharacter&的参数的类型,则GameCharacter需要事先声明.
我的第二个问题是如何理解typedef声明
它声明了一个类型名称HealthCalcFunc,它是一种指向函数的指针,它const GameCharacter&作为参数并返回int.
以及如何使用它?
正如代码示例所示,
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc) // declare a parameter with type HealthCalcFunc;
// the default argument is function pointer to defaultHealthCalc
: healthFunc(hcf) // initialize healthFunc with hcf
{}
int healthValue() const
{return healthFunc(*this); } // invoke the function pointed by healthFunc
HealthCalcFunc healthFunc; // declare a member with type HealthCalcFunc
Run Code Online (Sandbox Code Playgroud)
Rak*_*111 11
由于使用了前向声明defaultHealthCalc,因此需要前进声明GameCharacter.如果没有前向声明,编译器将不会知道稍后会有一个名为的类型GameCharacter,因此您需要转发声明它,或者在函数声明之前移动定义.
这typedef意味着要命名类型int(*)(const GameCharacter&) HealthCalcFunc.这是一个指向a的函数指针int(const GameCharacter&).因此,typedef非常难以理解,建议使用using声明:
using HealthCalcFunc = int(*)(const GameCharacter&);
Run Code Online (Sandbox Code Playgroud)
typedef int (*HealthCalcFunc)(const GameCharacter&);
Run Code Online (Sandbox Code Playgroud)
声明一个函数指针类型的typedef命名HealthCalcFunc,其中函数签名返回a int并获取参数const GameCharacter&.
需要前向声明,因为该类用作参数类型typedef.
所以我的第一个问题是为什么作者在这里使用前向声明?
这样编译器就知道GameCharacter在int defaultHealthCalc(const GameCharacter& gc);遇到该行时它是一个有效的名称.
我的第二个问题是如何理解typedef声明以及如何使用它?
理想情况下,您不再使用它.
从C++ 11开始,它using是一个更好的选择,因为它更具可读性; 与typedef'ed函数指针不同,它清楚地将名称与名称描述的名称分开.比较一下:
Run Code Online (Sandbox Code Playgroud)typedef int (*HealthCalcFunc)(const GameCharacter&);
有了这个:
using HealthCalcFunc = int (*)(const GameCharacter&);
Run Code Online (Sandbox Code Playgroud)
在该typedef版本中,名称HealthCalcFunc由名称描述的名称左右包围.这会伤害可读性.
但代码仍然可以改进,因为C++ 11也std::function作为函数指针之上的替代和/或抽象层引入.
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
Run Code Online (Sandbox Code Playgroud)
这是如此可读,几乎没有必要解释.HealthCalcFunc是一个返回int并取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;
};
Run Code Online (Sandbox Code Playgroud)
最棒的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));
}
Run Code Online (Sandbox Code Playgroud)
另请参阅我应该在C++中使用std :: function还是函数指针?.