2013-05-27 58 views
9

Tôi có hai chức năng với số biến và các loại đối sốcon trỏ hàm chức năng khác nhau với các đối số khác nhau trong C

double my_func_one(double x, double a, double b, double c) { return x + a + b + c } 
double my_func_two(double x, double p[], double c) { return x + p[0] + p[1] + c } 

Tôi muốn sử dụng một con trỏ đến một chức năng để các chức năng tôi định nghĩa ở trên dựa trên một số điều kiện nhận được đúng ví dụ

if (true == condition_1) 
    pfunc = my_func_one; 
else if (true == condition_2) 
    pfunc = my_func_two; 

// The function that will use the function I passed to it 
swap_function(a, b, pfunc); 

Câu hỏi của tôi là, đối với trường hợp này, tôi có thể xác định con trỏ hàm không? Nếu có, làm thế nào?
Sự hiểu biết của tôi là nguyên mẫu của con trỏ hàm phải giống nhau đối với tất cả các hàm mà nó có thể được trỏ tới.

typedef double (*pfunction)(int, int); 

Trong trường hợp của tôi, chúng không giống nhau. Có cách nào khác để làm điều này?

Ngôn ngữ

Tôi đang phát triển trong C và tôi đang sử dụng gcc 4.4.3 biên dịch/mối liên kết

+1

Đặt con trỏ hàm thành 'void *', sau đó thực hiện sắp xếp đúng khi được gọi? Bạn mất tất cả các loại an toàn loại mặc dù. –

Trả lời

9

Câu hỏi của tôi là, cho kịch bản này, Tôi có thể ở tất cả các định nghĩa một con trỏ hàm?

số (khác hơn bởi typecasting bẩn.)

Có cách nào khác để làm điều này?

Đặt cược tốt nhất của bạn là tạo hàm bao bọc cho một trong các chức năng hiện có của bạn. Ví dụ:

double my_func_one_wrapper(double x, double p[], double c) { 
    return my_func_one(x, p[0], p[1], c); 
} 

Bằng cách đó, bạn có hai hàm có cùng chữ ký và do đó cùng loại con trỏ chức năng.

+0

Xin cảm ơn @Oli Charlesworth và những người khác vì câu trả lời thực sự nhanh chóng của họ. – fahad

1

Hiểu biết của bạn là đúng sự thật.
Chữ ký của con trỏ hàm của bạn phải khớp với (các) hàm tương ứng.

Cân nhắc learncpp.com:

Cũng giống như người ta có thể khai báo một con trỏ không đổi cho một biến, nó cũng có thể đến> khai báo một con trỏ không liên tục để một hàm. Cú pháp để làm như vậy là một trong những điều xấu nhất> bao giờ bạn sẽ thấy:

// pFoo is a pointer to a function that takes no arguments and returns an integer 
int (*pFoo)(); 

Các ngoặc xung quanh * pFoo là cần thiết vì lý do ưu tiên, như int *pFoo() sẽ được hiểu như là một hàm có tên pFoo không có tham số và trả về một con trỏ tới một số nguyên.

Trong đoạn mã trên, pFoo là con trỏ đến hàm không có tham số và trả về số nguyên. pFoo có thể “trỏ” đến bất kỳ hàm nào khớp với chữ ký này.

...

Lưu ý rằng chữ ký (tham số và giá trị trả về) của con trỏ hàm phải khớp với chữ ký của hàm.

+1

Điều này không thực sự trả lời câu hỏi ... –

+0

Đã sửa bài đăng của tôi –

1

Điều bạn muốn là có thể, nhưng hơi bẩn. Con trỏ chức năng có thể được đúc với nhau mà không làm mất thông tin. Điều quan trọng là bạn phải luôn luôn có gọi một hàm thông qua con trỏ như vậy chỉ với một chữ ký tương ứng với định nghĩa của nó. Vì vậy, nếu bạn truyền lại trước khi gọi (các) hàm và gọi với các đối số chính xác, tất cả sẽ ổn.

14

Cách sạch để làm điều đó là sử dụng một công đoàn:

typedef union { 
    double (*func_one)(double x, double a, double b, double c); 
    double (*func_two)(double x, double p[], double c); 
} func_one_two; 

Sau đó, bạn có thể khởi tạo một thể hiện của các công đoàn, và bao gồm các thông tin cho swap_function chức năng để nói trước với các lĩnh vực có giá trị:

func_one_two func; 

if (condition_1) 
    func.func_one = my_func_one; 
else if (condition_2) 
    func.func_two = my_func_two; 

// The function that will use the function I passed to it 
swap_function(a, b, func, condition_1); 

Giả định rằng swap_function có thể biết dựa trên condition_1false mà nó phải giả định condition_2. Lưu ý rằng công đoàn được truyền theo giá trị; nó chỉ là một con trỏ chức năng có kích thước sau khi tất cả vì vậy đó không phải là đắt hơn so với đi qua một con trỏ đến nó.

-2

Một ví dụ về cách tiếp cận Typecasting để sử dụng cùng một con trỏ hàm cho các hàm khác nhau của các nguyên mẫu khác nhau. <>

#include <stdio.h> 
typedef void (*myFuncPtrType) (void); 

typedef int (*myFunc2PtrType)(int, int); 

typedef int * (*myFunc3PtrType)(int *); 

static void myFunc_1 (void); 
static int myFunc_2 (int, int); 
static int* myFunc_3 (int *); 

const myFuncPtrType myFuncPtrA[] = { 
            (myFuncPtrType)myFunc_1, 
            (myFuncPtrType)myFunc_2, 
            (myFuncPtrType)myFunc_3 
}; 

static void myFunc_1 (void) 
{ 
    printf("I am in myFunc_1 \n"); 
} 

static int myFunc_2 (int a, int b) 
{ 
    printf("I am in myFunc_2\n"); 
    return (a+b); 
} 

static int* myFunc_3 (int *ptr) 
{ 
    printf("I am in myFunc_3\n"); 
    *ptr = ((*ptr) * 2); 
    return (ptr+1); 
} 

int main(void) { 
    // your code goes here 
    int A[2],C; 

    int* PTR = A; 

    (*(myFuncPtrA[0]))(); 

    A[0]=5; 
    A[1]=6; 

    C = ((myFunc2PtrType)(*(myFuncPtrA[1])))(A[0],A[1]); 

    printf("Value of C: %d \n", C); 

    printf("Value of PTR before myFunc_3: %p \n", PTR); 
    printf("Value of *PTR before myFunc_3: %d \n", *PTR); 

    PTR = ((myFunc3PtrType)(*(myFuncPtrA[2])))(&A); 

    //Lets look how PTR has changed after the myFunc_3 call 

    printf("Value of PTR after myFunc_3: %p \n", PTR); 
    printf("Value of *PTR after myFunc_3: %d \n", *PTR); 


    return 0; 
} 
+1

Bạn có thể thêm mô tả về những gì bạn đã làm không? Thay vì chỉ dán mã. – kaldoran

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