How to understand typedef in this declaration

I recently read the book Effective C ++, and there is a typedef declaration in Item 35 that bothers me.

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; }; 

So my first question is: why does the author use a direct ad here? Is there any specific reason?

And my second question: how can I understand typedef declaration and how to use it? I just know something like typedef int MyInt;

+5
source share
5 answers

So my first question is why is the author using a direct ad here?

So, the compiler knows that GameCharacter is a valid name when the string int defaultHealthCalc(const GameCharacter& gc); .

And my second question: how to understand typedef declaration and how to use it?

Ideally, you no longer use it.

Starting with C ++ 11, using is an excellent alternative because it is more readable; unlike typedef 'ed function pointers, it clearly separates the name from the name that describes the name. Compare this:

 typedef int (*HealthCalcFunc)(const GameCharacter&); 

Wherein:

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

In the typedef version, the name HealthCalcFunc is surrounded on both sides by what the name describes. This affects readability.


But the code can still be improved, because C ++ 11 also introduced std::function as an alternative and / or level of abstraction over function pointers.

 using HealthCalcFunc = std::function<int(const GameCharacter&)>; 

It is so readable that it hardly needs to be explained at all. HealthCalcFunc is a function that returns int and accepts const GameCharacter& .

The defaultHealthCalc function fits into this definition. Here is a complete example:

 #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; }; 

The great thing about std::function is that you are not limited to stand-alone functions. You can pass each function. Here are some examples:

 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)); } 

See also Should I use std :: function or function pointer in C ++? .

+8
source

So my first question is why is the author using a direct ad here?

Since the declaration of the defaultHealthCalc function uses const GameCharacter& as the parameter type, GameCharacter must be declared in advance.

And my second question is how to understand typedef declaration

It declares a name of type HealthCalcFunc , which is a type of function pointer that takes const GameCharacter& as a parameter and returns an int .

and how to use it?

As the code example showed,

 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 
+13
source

The defaultHealthCalc forward declaration using GameCharacter requires a forward declaration. Without a direct declaration, the compiler will not know that a type named GameCharacter will exist later, so you need to send it to declare or transfer the definition before declaring the function.

That typedef means type name int(*)(const GameCharacter&) HealthCalcFunc . This is a function pointer to int(const GameCharacter&) . For this reason, typedefs are pretty unreadable, we recommend using using instead:

 using HealthCalcFunc = int(*)(const GameCharacter&); 
+11
source
 typedef int (*HealthCalcFunc)(const GameCharacter&); 

Declares a typedef named HealthCalcFunc for the function pointer type, where the function signature returns int and accepts the const GameCharacter& parameter const GameCharacter& .

A direct declaration is required because this class is used as the parameter type in a typedef .

+9
source

A promising GameCharacter ad is not strictly required; a function declaration might read:

 int defaultHealthCalc(const class GameCharacter& gc); 

which has the same effect as the source code. But it is considered more readable in order to have a forward declaration in its own line.

+2
source

Source: https://habr.com/ru/post/1265346/


All Articles