cuốn sách gpt4 ai đã làm

Lệnh gọi lại C++ cho các hàm không tĩnh giữa các lớp khác nhau

In lại Tác giả: Walker 123 Thời gian cập nhật: 27-11-2023 23:22:57 30 4
mua khóa gpt4 Nike

Tôi có một lớp A mà tôi dự định đưa vào thư viện dùng chung khi nó tương tác với trình điều khiển thiết bị.

Tôi có một lớp B, trong tương lai có thể là C, D, E..., lớp này sẽ sử dụng lớp A từ thư viện dùng chung.

Tôi muốn thiết lập chức năng của các hàm gọi lại trong lớp A để các hàm thành viên không tĩnh của các lớp B, C, D, E... sẽ được lớp A gọi khi một sự kiện cụ thể xảy ra.

Tôi đã tìm kiếm trên Google các hàm gọi lại trong C++ nhưng nhận thấy rằng các định nghĩa gọi lại kiểu C không hỗ trợ các hàm thành viên không tĩnh.

Nó có thể được thực hiện bằng cách sử dụng con trỏ hàm không?

Vui lòng đưa ra một số gợi ý về lệnh gọi lại trong C++ mà không vi phạm khái niệm OOPS.

Tôi cũng đã nghĩ đến một thư viện tên là "Boost" cung cấp chức năng tương tự, nhưng tôi muốn tránh chi phí cho một thư viện bổ sung càng nhiều càng tốt. Có nên sử dụng Boost cho chức năng gọi lại không?

biên tập: B, C, D, E sẽ không chia sẻ bất kỳ hệ thống phân cấp nào, chúng sẽ là các lớp hoàn toàn độc lập. Nhưng tất cả chúng sẽ có các đối tượng thuộc lớp A. Lớp A cũng sẽ có chức năng public để thiết lập chức năng gọi lại.

câu trả lời hay nhất

Nếu bạnthực tếĐể tránh chi phí gần như không quan trọng của các trình bao bọc hàm đa hình, một tùy chọn là đặt các hàm này ở trạng thái tĩnh và để chúng lấy "dữ liệu người dùng"trống* Các tham số trỏ đến phiên bản thích hợp của lớp mà hàm này thuộc về. bên trong một hàm tĩnh và sau đó chuyển đổi về loại thích hợp:

#include 

cấu trúc A{
typedef void (*callback_type)(void*, int);
gọi lại_type gọi lại;
void* user_data;
void set_callback(callback_type cb, void* ud){
gọi lại = cb;
}
void gọi(){ gọi lại(user_data, 42 }
};

cấu trúc B{
static void cb_foo(void* vself, int data){
B* self = static_cast(vself);
tự->foo(dữ liệu);
}
void foo(int data){ std::cout << data * 2 << "\n" }
};

cấu trúc C{
static void cb_bar(void* vself, int data){
C* self = static_cast(vself);
tự->thanh(dữ liệu);
}
void bar(int data){ std::cout << data / 2 << "\n" }
};

int chính(){
Một;
Bb;
a.set_callback(&B::cb_foo, &b);
a.invoke();
C c;
a.set_callback(&C::cb_bar, &c);
a.invoke();
}

Ví dụ trực tiếp trên Ideone.

Tuy nhiên, cá nhân tôi khuyên bạn nên sử dụng std::chức năng, vì điều trên bị hạn chế nghiêm trọng về số lần gọi lại được chấp nhận. std::chức năng là một trình bao bọc hàm đa hình, có nghĩa là nó có thể lấy một con trỏ hàm bình thường, một con trỏ hàm thành viên hoặc thậm chí là một functor (đối tượng hàm) và gọi tất cả chúng theo cùng một cách. with cho phép bạn liên kết các tham số với các hàm std::liên kết Cùng nhau, bạn có thể dễ dàng gọi lại các chức năng thành viên. Boost cũng cung cấp chúng (Tăng cường.Chức năng,Boost.Bind).

#include 
#include // C++11
//#include
//#include

cấu trúc A{
std::function gọi lại;
void gọi(){ gọi lại(42);
};

cấu trúc B{
void foo(int data){ std::cout << data * 2 << "\n" }
};

cấu trúc C{
void bar(int data){ std::cout << data / 2 << "\n" }
};

int chính(){
sử dụng không gian tên std::placeholders; // không gian tên dành cho phần giữ chỗ đối số cho std::bind
// không cần thiết cho Boost.Bind
Một;
Bb;
a.callback = std::bind(&B::foo, &b, _1);
a.invoke();
C c;
a.callback = std::bind(&C::bar, &c, _1);
a.invoke();
};

Ví dụ trực tiếp trên Ideone.

về cơ bản std::liên kết thực hiện tự động những gì bạn phải làm thủ công trong phiên bản đầu tiên, nó lưu con trỏ đối tượng và gọi các hàm thành viên của nó. Tuy nhiên nó không được thông qua trống* con trỏ để làm điều này, thay vào đó std::liên kết Trả về một loại chất kết dính khác nhau cho mỗi con trỏ đối tượng khác nhau. đây là thứ bạn cần std::chức năng bởi vì nó không quan tâm bạn vượt qua nó như thế nào.

Về lệnh gọi lại C++ cho các hàm không tĩnh giữa các lớp khác nhau, chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/11522422/

30 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress