2012-06-04 72 views
6

Xin chào bạn bè,
How can I use an array of function pointers?
Nếu chúng ta sẽ thấy liên kết ở trên, nó cho chúng ta biết cách hoạt động của con trỏ hàm.
Bây giờ câu hỏi đặt ra là tại sao tôi nên chọn con trỏ hàm?
Tại sao tôi không thể sử dụng chức năng gọi trực tiếp?
Tôi sẽ nhận được lợi ích gì với con trỏ hàm?
ví dụSự khác biệt giữa hàm Pointer vs Function Call là gì?

enum{a, b, c}; 
void A(); 
void B(); 
void C(); 
void (*fun[3])() = {A, B, C}; 

Now when I need to call a function I am doing like, 
fun[a](); // This calls function A 
// And so on... 

Cùng thể được thực hiện trong chức năng cũng

gọi như khi tôi cần phải gọi hàm A, B hoặc C. trực tiếp tôi có thể đúng như

A(); 
B(); 
or 
C(); 

Vậy tại sao function pointer?

+2

Tôi không biết tại sao có hai phiếu bầu âm cho câu hỏi của mình. Nhưng có một điều tôi biết, điều đó không có nghĩa là nếu bạn biết điều gì đó mà mọi người nên biết. Nhưng dù sao đi nữa hay không, cũng không có vấn đề gì nếu các nghi ngờ của tôi bị xóa. –

Trả lời

5

Bây giờ câu hỏi đặt ra là tại sao tôi nên chọn con trỏ hàm?
Tôi sẽ nhận được lợi ích gì với con trỏ hàm?

Bạn sử dụng con trỏ hàm khi bạn cần triển khai cơ chế Không đồng bộ.
Bạn cần một hàm được gọi là không đồng bộ khi điều gì đó xảy ra.
Bạn sẽ biết chức năng nào để gọi?
Địa chỉ của mọi chức năng là Duy nhất, Vì vậy, bạn cần sử dụng và lưu trữ địa chỉ hàm.
Bạn lưu trữ địa chỉ hàm này ở đâu?
Một chức năng con trỏ

2

Con trỏ hàm là con trỏ (như con trỏ biến) trỏ đến địa chỉ của hàm. Họ thực sự gọi chức năng cơ bản khi bạn dereference họ như một cuộc gọi chức năng nào.

Ưu điểm chính của một con trỏ hàm là bạn có thể vượt qua nó để chức năng khác như một tham số ví dụ ...

3

Theo kinh nghiệm của tôi, con trỏ chức năng được sử dụng chủ yếu để vượt qua một chức năng như một tham số sang một hàm khác.

Nhìn vào mã của bạn, chúng cũng có thể được sử dụng như với mảng, vì vậy bạn có thể lặp qua toàn bộ mảng (có thể bao gồm hàng trăm con trỏ hàm) và nó sẽ thực thi tất cả.

11

Có rất nhiều lý do để sử dụng một con trỏ hàm, đặc biệt là để làm những việc quát trong C.

Nơi chính bạn sẽ thấy chúng được sử dụng như một tham số để một hàm.Ví dụ với chức năng bsearch, nó sử dụng một chức năng so sánh, thông qua như là một con trỏ hàm, để so sánh các mặt hàng và sắp xếp dữ liệu:

void *bsearch(const void *key, const void *base, 
        size_t nmemb, size_t size, 
        int (*compar)(const void *, const void *)); 

đó cho phép bsearch là chung chung và sắp xếp bất kỳ loại dữ liệu, kể từ duy nhất mà chức năng so sánh phải biết loại dữ liệu.


Một cách khác là phải tránh nhiều lần kiểm tra. I E.

void makePizza(void) { } 

void bakeCake(void) { } 

iWantPizza = 1; 
... 
if (iWantPizza) 
    makePizza(); 
else 
    bakeCake(); 
/* want to call the same function again... */ 
if (iWantPizza) 
    makePizza(); 
else 
    bakeCake(); 

.. 

/* alternative */ 
void (*makeFood)(void) = iWantPizza ? makePizza : bakeCake; 

makeFood(); 
/* want to call the same function again... */ 
makeFood(); 
6

Ví dụ bạn đã thể hiện, một điều nữa có thể được thực hiện.

Cho phép nói rằng có nhiều chức năng cần chạy cho một số thao tác thiết bị. Theo cách đơn giản, bạn có thể viết tất cả các cuộc gọi chức năng trong một chức năng chính khác và gọi hàm chính.

Một cách khác để thực hiện điều này là viết tất cả tên hàm trong dấu ngoặc nhọn và gọi từng hàm bằng cách sử dụng con trỏ hàm và vòng lặp. Điều đó có vẻ thông minh. Tôi không chắc chắn như thế nào giúp bạn trong cách tốt hơn nhưng tôi thấy điều này trong mã hạt nhân Linux.


Tôi đồng ý với tất cả các câu trả lời tại đây. Ngoài ra tôi có một số phán đoán của riêng tôi để sử dụng con trỏ hàm.

Cho phép lấy ví dụ về một số phép tính toán phức tạp (như in Fibonacci, tích hợp, Xáo trộn Xform, v.v ...).

Bạn có hàm FX (tính toán toán học phức tạp hoặc bất kỳ thứ gì khác) mà bạn sử dụng nhiều lần trong chương trình của mình. Chức năng này được sử dụng trong nhiều công việc khác nhau.

Sau khi sử dụng chương trình của bạn trong vài tháng, bạn sẽ thấy rằng, đối với một số công việc, bạn có thể cải thiện chức năng và một số chức năng, hiện tại là tốt nhất. Bạn sẽ làm gì? Viết một hàm mới, đi và thay đổi tên hàm ở tất cả các vị trí.

Mỗi khi bạn tìm thấy thứ gì đó tốt hơn, bạn sẽ làm tương tự.

Thay vào đó, hãy sử dụng con trỏ hàm khác nhau cho công việc khác nhau. Ở giai đoạn ban đầu, tất cả các con trỏ có thể trỏ đến một hàm. Khi bạn phát hiện một chức năng tốt hơn cho một số công việc, chỉ cần chuyển hướng con trỏ và bạn đã hoàn tất.


Tạo một tình huống khác. Ở đây, bạn có một mã thực sự lớn như hệ điều hành điện thoại di động. (không hoàn toàn mở nhưng được biên dịch một nửa). Bạn cần thêm trình điều khiển bluetooth vào một phần cứng cụ thể.

Bây giờ, bạn có thể thêm hoặc bạn có thể thoát là tùy chọn có sẵn trong OS.

Bạn có thể cần bật/tắt bluetooth từ nhiều nơi.

Vì vậy, hệ điều hành là gì, nó làm cho một con trỏ chức năng bật Bluetooth ON và sử dụng nó bất cứ nơi nào nó là cần thiết. Mã này đã được biên dịch nên bạn không thể thêm mã của mình vào đó. Nhưng những gì có thể được thực hiện là, bạn có thể viết chức năng và làm cho con trỏ trỏ đến chức năng của bạn.

Đây là những gì tôi đã thấy trong Hệ điều hành Android.(không chính xác nhưng gần hơn)

+1

Tôi thực sự thích ví dụ với phép tính toán phức tạp. – johnny

3

Sự khác biệt giữa Hàm con trỏ chức năng so với Cuộc gọi hàm là gì?

Cũng giống như sự khác biệt giữa yêu cầu trình biên dịch "cho tôi biết địa chỉ của Thư viện Quốc gia (tôi có thể muốn đến đó sau này và tôi muốn sẵn sàng để làm điều đó)", thay vì "đưa tôi đến Thư viện Quốc gia ngay bây giờ (nhưng tôi sẽ không chú ý đến cách bạn đưa tôi đến đó vì vậy đừng mong tôi biết sau này) ". Quan trọng, nếu bạn yêu cầu địa chỉ/con trỏ, bạn có thể viết nó ở một nơi nào đó như "chuyến đi lớn vào chiều Chủ nhật tới" ... bạn thậm chí không cần phải nhớ rằng đó là Phòng trưng bày Quốc gia bạn sẽ đến - nó có thể là một bất ngờ thú vị khi bạn đến đó - nhưng bạn ngay lập tức biết giải trí của chủ nhật của bạn tất cả được sắp xếp.

Tôi sẽ nhận được lợi ích gì với con trỏ hàm?

Vâng, như trên, tại thời điểm bạn đặt con trỏ hàm, bạn cần đưa ra quyết định về nơi bạn sẽ gọi sau, nhưng sau đó bạn có thể quên mọi lý do đưa ra quyết định đó và chỉ biết rằng tất cả các điểm đến sau này đều sẵn sàng để sử dụng. Vào thời điểm bạn đang thực sự làm công cụ ... "thói quen chủ nhật của tôi: ngủ đến 10 tuổi, ăn bữa sáng lớn, trở lại giường, tắm, nếu tôi có nhiều tiền thì hãy đi vào chủ nhật của tôi buổi chiều chuyến đi lớn, gặp gỡ bạn bè cho bữa tối "... quyết định trước đó chỉ đá vào để đưa bạn đến phòng trưng bày. Điều quan trọng là bạn có thể tiếp tục sử dụng lịch chủ nhật quen thuộc của bạn và bắt đầu "chỉ" "chuyến đi lớn" vào chiều chủ nhật tiếp theo "địa chỉ/con trỏ tại địa điểm mới khi họ bắt mắt bạn, ngay cả khi chúng không tồn tại khi lịch biểu chung của bạn được hình thành.

Bạn thấy tính linh hoạt sau thực tế này để thay đổi đích được gửi đến một bước trong một thói quen cũ được minh họa tốt theo đề cập của AusCBloke là bsearch. qsort là một ví dụ điển hình khác - nó biết logic hình ảnh lớn về phân loại hiệu quả các mảng tùy ý, nhưng phải được cho biết đi đâu để so sánh hai trong số những thứ bạn đang thực sự sử dụng nó.

1

Đây là những ví dụ hay, đặc biệt là ví dụ đầu tiên ở trên của Urvish. Tôi đã tự hỏi điều tương tự, và tôi nghĩ câu trả lời là hoàn toàn thiết kế. Trong tâm trí của tôi, chúng có cùng kết quả, như trong bạn có thể trỏ đến một hàm và nhận dấu + b hoặc bạn chỉ có thể gọi hàm một cách thường xuyên và nhận dấu +, và với các ví dụ trên SO, chúng thường nhỏ và tầm thường để minh họa. Nhưng, nếu bạn có chương trình dòng C 10k và bạn phải thay đổi điều gì đó năm mươi lần vì bạn đã thực hiện thay đổi, bạn có thể nhận được khá nhanh chóng tại sao bạn muốn sử dụng con trỏ hàm.

Nó cũng giúp bạn đánh giá cao thiết kế của ngôn ngữ OOP và triết lý đằng sau OOD.

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