最近,我读了《有效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;
};
所以我的第一个问题是:为什么作者在这里使用转发声明?有什么具体原因吗?
我的第二个问题是:我如何理解typedef声明,以及如何使用它?我只知道typedef int MyInt之类的东西;
所以我的第一个问题是,为什么作者在这里使用forward声明?
以便编译器知道游戏字符
是一个有效的名称,当 int 默认健康计算器(const 游戏字符
而我的第二个问题是如何理解typedef声明,如何使用它?
理想情况下,您不再使用它。
从C 11开始,
使用
是一个更好的选择,因为它更具可读性;与 typedef'ed
函数指针不同,它清楚地将名称与名称所描述的名称分开。比较一下:
typedef int (*HealthCalcFunc)(const GameCharacter&);
有了这个:
using HealthCalcFunc = int (*)(const GameCharacter&);
在
类型定义
版本中,名称“健康计算器”的两
侧被该名称所描述的内容所包围。这会损害可读性。
但是代码仍然可以改进,因为C11还引入了
std::function
作为函数指针之上的替代和/或抽象层。
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
这是如此易读,几乎不需要解释。
HealthCalcFunc
是一个返回int
并接受const GameCharacter的函数
< code>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;
};
< code>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还是函数指针?。
因为< code>defaultHealthCalc的前向声明使用< code>GameCharacter,所以需要前向声明。如果没有前向声明,编译器不会知道以后会有一个名为< code>GameCharacter的类型,因此您需要前向声明它,或者将定义移到函数声明之前。
< code>typedef意味着将类型命名为< code>int(*)(const GameCharacter
using HealthCalcFunc = int(*)(const GameCharacter&);
所以我的第一个问题是为什么作者在这里使用前置声明?
因为函数的声明defaultHealthCalc
使用了const GameCharacter
我的第二个问题是如何理解typedef声明
它声明了一个类型名HealthCalcFunc
,这是一种指向函数的指针类型,它接受const GameCharacter
以及如何使用?
正如代码示例所示,
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
问题内容: 我正在尝试解析方法声明。基本上,我需要获取接收方基本类型()和返回类型(和)的语法节点。该程序包看起来很简单,但是由于某种原因,我没有获得所需的数据(即,字段为nil)。 唯一有用的数据似乎仅在类型为字段的字段中提供, 因此我认为我无法序列化它。 任何帮助,将不胜感激。代码如下: 操场 问题答案: 要获取类型,您需要查看可能是an 或an 的属性。 这里看看这个:
问题内容: 如果我在Swift中需要自定义类型,可以,该怎么办?(类似于闭包语法typedef) 问题答案: 使用关键字代替
我是Spring的新手,并试图理解在我的Spring配置文件中声明的bean标记,如下所示: 我正在努力理解这5行代码。第一行表示它是一个XML文件。请有人帮我理解其他4行,以及向Spring应用程序提供这些信息的原因。
这在这个回答中出现了,并且: 在Apple LLVM 9.1.0 CLANG-902-0.39.2中,的引用第一个并打印“1”。 GCC 8.2不接受此源文本。,抱怨:“错误:以前声明为'static‘的变量重新声明为'extern'”。 C 2018 6.2.2 4规定: 由于有两个先验声明,因此以下每个“if”子句的条件为真,第一个用于第一个先验声明,第二个用于第二个先验声明: ……如果前面声
问题内容: 我正在使用espresso-contrib在上执行操作,它可以正常运行,例如: 我需要对此进行断言。像这样: 但是,由于RecyclerViewActions当然期望执行某个操作,因此它说出了错误的第二个参数类型。浓咖啡没有。 有什么方法可以在回收者视图上执行断言吗? 问题答案: 您应该查看Danny Roa的解决方案Custom RecyclerView Actions并按以下方式
Section Contents 基本内容 具体细节