当前位置: 首页 > 知识库问答 >
问题:

如何理解此声明中的typedef

徐阳炎
2023-03-14

最近,我读了《有效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之类的东西;

共有3个答案

涂溪叠
2023-03-14

所以我的第一个问题是,为什么作者在这里使用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还是函数指针?。

诸葛皓
2023-03-14
匿名用户

因为< code>defaultHealthCalc的前向声明使用< code>GameCharacter,所以需要前向声明。如果没有前向声明,编译器不会知道以后会有一个名为< code>GameCharacter的类型,因此您需要前向声明它,或者将定义移到函数声明之前。

< code>typedef意味着将类型命名为< code>int(*)(const GameCharacter

using HealthCalcFunc = int(*)(const GameCharacter&);

汤玉宸
2023-03-14

所以我的第一个问题是为什么作者在这里使用前置声明?

因为函数的声明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 基本内容 具体细节