Vì vậy, câu hỏi đầu tiên của tôi là tại sao tác giả sử dụng phía trước tuyên bố đây?
Để trình biên dịch biết rằng GameCharacter
là tên hợp lệ khi gặp phải dòng int defaultHealthCalc(const GameCharacter& gc);
.
Và câu hỏi thứ hai của tôi là cách hiểu khai báo typedef và cách sử dụng?
Lý tưởng nhất, bạn hãy không sử dụng nữa.
Bắt đầu với C++ 11, using
là giải pháp thay thế cao cấp vì nó dễ đọc hơn; không giống như typedef
'con trỏ chức năng được chỉnh sửa, nó sẽ tách biệt tên với tên mô tả. Hãy so sánh này:
typedef int (*HealthCalcFunc)(const GameCharacter&);
Với điều này:
using HealthCalcFunc = int (*)(const GameCharacter&);
Trong phiên bản typedef
, tên HealthCalcFunc
được bao quanh trên cả hai mặt bằng đó mà tên mô tả. Điều này làm tổn thương khả năng đọc.
Nhưng mã vẫn có thể được cải thiện, bởi vì C++ 11 cũng giới thiệu std::function
như một sự thay thế và/hoặc một lớp trừu tượng trên con trỏ hàm.
using HealthCalcFunc = std::function<int(const GameCharacter&)>;
Điều này rất dễ đọc, hầu như không phải giải thích chút nào. HealthCalcFunc
là hàm trả về số int
và mất const GameCharacter&
.
Chức năng defaultHealthCalc
phù hợp với định nghĩa này. Dưới đây là ví dụ đầy đủ:
#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;
};
Điều tuyệt vời về std::function
là bạn không bị giới hạn chức năng tự do. Bạn có thể truyền mọi thứ giống như chức năng. Dưới đây là một số ví dụ:
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));
}
Xem thêm Should I use std::function or a function pointer in C++?.
_ "Vì mã vẫn có thể được ** cải thiện **" _: đề cập đến 'std :: function' ở đây là thích hợp, nhưng nó là một sự thay thế hoàn toàn khác, và cho một ví dụ đơn giản như thế này, nó có thể được đề cập đến những cải tiến khi chuyển từ loại con trỏ hàm trọng lượng nhẹ sang loại hoàn toàn khác và so với sinh vật "nặng" của 'std :: function'. Cả hai đều có vị trí của chúng (chủ yếu là, imo, 'std :: function' nên được ưu tiên, nhưng khi làm việc với các API cũ hơn ...), nhưng là các khái niệm rất khác nhau, và có nên sử dụng một khái niệm khác hay không? . – dfri
@dfri: Tôi nghĩ rằng 'std :: function' là đơn giản hơn nhiều để viết, đọc và áp dụng hơn một con trỏ hàm, vì vậy tôi xem nó là giải pháp tiêu chuẩn, trong khi con trỏ hàm là những con thú có mục đích đặc biệt. –
Có, tôi đồng ý, lưu ý chỉnh sửa ninja của tôi.Tuy nhiên, khi đề cập đến 'std :: function' như là một sự cải tiến luôn luôn, nó có thể có giá trị để chỉ ra rằng có những tình huống mà một con trỏ hàm đơn giản là thích (hoặc thậm chí là thay thế duy nhất). Dù sao, câu trả lời tốt, chỉ là một đường nhỏ bên cạnh của tôi ở trên! – dfri