Tôi nghĩ rằng một giải pháp tốt hơn sẽ được thực hiện của một phương pháp ảo, chứ không phải có B tái thực hiện các giao diện A được gắn vào (điều này có thể yêu cầu công việc hơn chỉ xác định lại một chức năng), mà bạn có thể làm như thế này (ví dụ nên được hoàn khác với định nghĩa giao diện fooable):
#include <glib-object.h>
#include "fooable.h"
typedef struct {GObject parent;} A;
typedef struct {
GObjectClass parent;
gint (*foo) (Fooable *self, gdouble quux);
} AClass;
#define TYPE_A (a_get_type())
#define A_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST((cls), TYPE_A, AClass))
#define A_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_A, AClass))
gint a_foo_real (Fooable *self, gdouble quux) {
g_print("a_foo_real(%g)\n", quux);
return 5;
}
gint a_foo (Fooable *self, gdouble quux) {
return A_GET_CLASS(self)->foo(self, quux);
}
void implement_fooable (FooableIface *iface) {iface->foo = a_foo;}
void a_class_init (AClass *cls) {cls->foo = a_foo_real;}
void a_init (A *self) {}
G_DEFINE_TYPE_WITH_CODE(A, a, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(TYPE_FOOABLE, implement_fooable));
/* derive class B from A */
typedef struct {A parent;} B;
typedef struct {AClass parent;} BClass;
#define TYPE_B (b_get_type())
gint b_foo_real (Fooable *self, gdouble quux) {
g_print("b_foo_real(%g)\n", quux);
return 55;
}
void b_class_init (BClass *cls) {A_CLASS(cls)->foo = b_foo_real;}
void b_init (B *self) {}
G_DEFINE_TYPE(B, b, TYPE_A);
int main() {
g_type_init();
A *a = g_object_new(TYPE_A, NULL);
B *b = g_object_new(TYPE_B, NULL);
fooable_foo(FOOABLE(a), 87.0); // a_foo_real(87.0) and returns 5
fooable_foo(FOOABLE(b), 32.0); // b_foo_real(32.0) and returns 55
return 0;
}
đó là như ngắn gọn về một ví dụ như tôi có thể làm cho nó. Khi bạn gọi hàm fooable_foo()
, hàm sẽ xem xét vtable của nó cho hàm được xác định khi bạn triển khai giao diện là a_foo()
xem giao diện của lớp A để xác định hàm nào thực sự gọi. Định nghĩa lớp B ghi đè a_foo_real()
của lớp A với riêng nó. Nếu bạn cần b_foo_real
của lớp B để kết nối, điều đó đủ dễ dàng (sử dụng A_CLASS(b_parent_class)->foo()
được xác định cho bạn trong macro G_DEFINE_TYPE)
Tôi đề xuất gắn thẻ câu hỏi này là GObject vì nó có liên quan nhiều hơn GTK +. – ntd
Nhìn lại 2 năm sau, tôi thực sự cảm thấy may mắn vì tôi không cần phải chiến đấu với cái crap này nữa. – ablmf
Crap? ĐÂY LÀ GOBJEEECT! – ntd