2011-10-06 36 views
11

Câu hỏi khá nhiều nói lên tất cả.C: Làm thế nào tôi có thể sử dụng một mảng con trỏ hàm cho các hàm có số lượng tham số biến?

Tôi không chắc chắn cách thực hiện điều này và chưa đến bất cứ nơi nào gần bất kỳ thứ gì hoạt động.

Dưới đây là một số chức năng ví dụ:

add(int x, int y) { 
    return x+y; 
} 

mean(int x1, int y1, int x2, int y2) { 
    return (x1 + y1 + x2 + y2)/4; 
} 

Cho đến nay tôi đã cố gắng sử dụng typedef với cả hai, nhưng tôi không thể hình dung làm thế nào để làm một cái gì đó điểm đến một trong hoặc loại:

typedef int (*mathfunc2)(int x, int y); 
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2); 

????? func_table[2] = {add, mean}; 

Trả lời

25

Bạn cần phải chọn loại con trỏ hàm để sử dụng làm "con trỏ hàm chung" , sử dụng loại đó để xác định mảng của bạn và sử dụng các phôi rõ ràng. Đúc một kiểu con trỏ hàm khác và sau đó lại được đảm bảo để bảo toàn giá trị.

Nói cách khác:

typedef int (*generic_fp)(void); 

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean }; 

Sau đó, để gọi add, bạn cần phải cast nó trở lại đúng loại:

result = ((mathfunc2)func_table[0])(x, y); 

Bạn có thể xác định một số macro nếu bạn tìm thấy nó ngon miệng hơn:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2) 
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4) 

result = FUNC_2(func_table[0], x, y); 
+0

Điều đó chính xác đã làm được điều đó! Cảm ơn, thưa ngài. Tôi hy vọng sẽ nhớ điều này nếu tôi nhận được 15 danh tiếng và cung cấp cho bạn một mũi tên lên :) – vaughanj

+0

Tôi đã theo con trỏ hàm hoạt động khác với con trỏ void thông thường vì các tham số. Bạn không thể kết hợp các con trỏ hàm với các tham số khác nhau vì ngăn xếp sẽ bị hỏng khi dọn dẹp. Tôi đã hiểu nhầm điều gì chưa? – Ioan

+0

@Ioan: Bạn phải gọi hàm thông qua một con trỏ tương thích với kiểu khai báo của hàm - có nghĩa là nếu bạn đưa con trỏ hàm vào một kiểu khác để lưu trữ, bạn phải đưa nó trở lại đúng kiểu để gọi chức năng. Ví dụ trong câu trả lời này thực hiện điều này. – caf

0

Hai loại chức năng này không tương thích. Nói đúng ra, chúng có thể được thực hiện bằng cách sử dụng đối số hoàn toàn khác. Ví dụ, việc triển khai có thể chọn, tất cả các hàm có tối đa 3 tham số sẽ nhận chúng thông qua thanh ghi và tất cả các hàm khác sẽ nhận chúng thông qua ngăn xếp.

Điều bạn có thể làm là xác định cả hai hàm với thông số varargs để làm cho chúng tuân theo cùng một lược đồ truyền tham số.

Dù sao bạn định gọi các hàm này, không biết có bao nhiêu tham số mà chúng mong đợi?

3

Bạn có thể sử dụng Facade Pattern như thế này:

int add(int x, int y); 
int mean(int x1, int y1, int x2, int y2); 

typedef int (*operation_fp)(int argc, int* argv); 

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); } 
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); } 

operation_fp func_table[2] = { add_wrapper, mean_wrapper }; 

Mặc dù mã là xấu xí, nó hiện công việc. Bạn nên thêm một số logic xác nhận trong trình bao bọc.

1
int (*func[])() = { add, mean }; 
+0

Các con trỏ hàm của kiểu 'int (*) (int, int)' và 'int (*) (int, int, int, int)' là * không * tương thích với các con trỏ hàm của kiểu 'int (*) (int, ...) '. – caf

+0

chắc chắn, Chỉnh sửa thành() – BLUEPIXY

Các vấn đề liên quan