Làm cách nào tôi có thể sử dụng CRTP trong C ++ để tránh chi phí cho các hàm thành viên ảo?
Làm cách nào tôi có thể sử dụng CRTP trong C ++ để tránh chi phí cho các hàm thành viên ảo?
Câu trả lời:
Có hai cách.
Cách đầu tiên là chỉ định giao diện tĩnh cho cấu trúc của các loại:
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo(); // required to compile.
};
struct your_type : base<your_type> {
void foo(); // required to compile.
};
Cách thứ hai là tránh sử dụng thành ngữ tham chiếu đến cơ sở hoặc con trỏ đến cơ sở và thực hiện việc nối dây tại thời điểm biên dịch. Sử dụng định nghĩa trên, bạn có thể có các hàm mẫu trông giống như sau:
template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
obj.foo(); // will do static dispatch
}
struct not_derived_from_base { }; // notice, not derived from base
// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload
Vì vậy, kết hợp định nghĩa cấu trúc / giao diện và loại trừ thời gian biên dịch trong các chức năng của bạn cho phép bạn thực hiện điều phối tĩnh thay vì điều phối động. Đây là bản chất của tính đa hình tĩnh.
not_derived_from_base
không có nguồn gốc từ base
, cũng không phải là nó có nguồn gốc từ base
...
Tôi đã tự mình tìm kiếm các cuộc thảo luận về CRTP. Todd Veldhuizen's Techniques for Scientific C ++ là một nguồn tài nguyên tuyệt vời cho điều này (1.3) và nhiều kỹ thuật nâng cao khác như các mẫu biểu thức.
Ngoài ra, tôi thấy rằng bạn có thể đọc hầu hết các bài báo gốc về C ++ Gems của Coplien trên Google books. Có lẽ vẫn vậy thôi.
dynamic_cast
hoặc các phương thức ảo.
Tôi đã phải tra cứu CRTP . Tuy nhiên, sau khi làm điều đó, tôi đã tìm thấy một số thông tin về Tính đa hình tĩnh . Tôi nghi ngờ rằng đây là câu trả lời cho câu hỏi của bạn.
Nó chỉ ra rằng ATL sử dụng mô hình này khá rộng rãi.
Đây câu trả lời Wikipedia có mọi thứ bạn cần. Cụ thể:
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Mặc dù tôi không biết điều này thực sự mua bạn bao nhiêu. Chi phí của một lệnh gọi hàm ảo là (tất nhiên là phụ thuộc vào trình biên dịch):
Trong khi tổng chi phí của đa hình tĩnh CRTP là: