2010-11-19 35 views
27

Cấu trúc có thể chứa các chức năng không?Các chức năng trong cấu trúc

+0

Có thể, nhưng không có lợi thế vốn có trong lập trình C thông thường. Trong C, tất cả các chức năng đều nằm trong không gian toàn cục, vì vậy bạn không bị ẩn thông tin bằng cách nhét chúng vào một hàm. Ví dụ của paxdiablo là một cách để tổ chức các hàm thành một cấu trúc, nhưng bạn phải xem có phải coi trọng từng cái một để sử dụng nó. Cấu trúc tổ chức tiêu chuẩn của C là Tệp, với các giao diện trong tiêu đề và triển khai trong nguồn. Đó là cách libc được thực hiện và đó là cách hầu hết tất cả các thư viện C được thực hiện. –

Trả lời

33

Không, nhưng chúng có thể chứa hàm con trỏ.

Nếu ý định của bạn là để làm một số hình thức đa hình trong C thì có, nó có thể được thực hiện:

typedef struct { 
    int (*open)(void *self, char *fspec); 
    int (*close)(void *self); 
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz); 
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz); 
    // And data goes here. 
} tCommClass; 

Các typedef trên là cho một cấu trúc tôi đã tạo cho một thư viện truyền thông mục đích chung. Để khởi tạo các biến, bạn sẽ:

tCommClass *makeCommTcp (void) { 
    tCommClass *comm = malloc (sizeof (tCommClass)); 
    if (comm != NULL) { 
     comm->open = &tcpOpen; 
     comm->close = &tcpOpen; 
     comm->read = &tcpOpen; 
     comm->write = &tcpWrite; 
    } 
    return comm; 
} 

tCommClass *makeCommSna (void) { 
    tCommClass *comm = malloc (sizeof (tCommClass)); 
    if (comm != NULL) { 
     comm->open = &snaOpen; 
     comm->close = &snaOpen; 
     comm->read = &snaOpen; 
     comm->write = &snaWrite; 
    } 
    return comm; 
} 

tCommClass *commTcp = makeCommTcp(); 
tCommClass *commSna = makeCommSna(); 

Sau đó, để gọi chức năng, một cái gì đó như:

// Pass commTcp as first params so we have a self/this variable 
// for accessing other functions and data area of object. 
int stat = (commTcp->open)(commTcp, "bigiron.box.com:5000"); 

Bằng cách này, một loại duy nhất có thể được sử dụng cho TCP, SNA, RS232 hoặc thậm chí cả tàu sân bay pidgeons, với chính xác cùng một giao diện.

+1

Vì vậy, đây cũng là một trong những khác biệt b/w struct và các lớp học? Bởi vì như tôi biết chỉ có sự khác biệt là struct có public mặc định và class mặc định là private – JoshMachine

+0

@Josh, tôi nghĩ bạn thực sự đúng về public/private là sự khác biệt duy nhất giữa struct/union trong C++. Câu hỏi này là về C. Tôi nghi ngờ các hàm _are_ được phép trong C++ vì 'struct xyz {int fn (void); } a; 'làm việc tốt trong g ++. – paxdiablo

+0

Ồ đúng, tôi không thấy thẻ C. +1 để xóa sự nghi ngờ! – JoshMachine

5

chỉnh sửa dọn dẹp lên mơ hồ với việc sử dụng 'kiểu dữ liệu'

Không có trong C. struct loại chỉ có thể chứa dữ liệu.

Từ mục 6.7.2.1 của tiêu chuẩn ISO C99.

Một cấu trúc hoặc công đoàn sẽ không chứa một thành viên với đầy đủ hoặc chức năng loại (vì thế, một cấu trúc sẽ không chứa một thể hiện của bản thân, nhưng có thể chứa một con trỏ đến một thể hiện của chính nó), trừ rằng thành viên cuối cùng của một cấu trúc có nhiều hơn một thành viên có tên có thể có loại mảng không đầy đủ; một cấu trúc như vậy (và bất kỳ công đoàn nào có chứa, có thể là đệ quy, một thành viên có cấu trúc như vậy) sẽ không phải là thành viên của một cấu trúc hoặc một phần tử của một mảng.

+0

+1 để chỉ ra tiêu chuẩn – Jay

+0

"chứa kiểu dữ liệu" là một sự mơ hồ nguy hiểm (ít nhất là cho người dùng C++, nơi họ có thể khai báo các loại) - "chứa dữ liệu" có vẻ chính xác hơn. Tất cả được thực hiện rõ ràng trong tiêu chuẩn mặc dù ... :-). –

0

Trong C, cấu trúc được phép chứa các giá trị dữ liệu chứ không phải các con trỏ hàm. Không được phép trong C. nhưng các công trình sau đây thực sự tốt khi được kiểm tra bằng gcc.

enter code here 

#include <stdio.h> 

struct st_func_ptr{ 
     int data; 
     int (*callback)(); 
}; 

int cb(){ 
     printf(" Inside the call back \n"); 
     return 0; 
} 

int main() { 
     struct st_func_ptr sfp = {10, cb}; 

     printf("return value = %d \n",sfp.callback()); 

     printf(" Inside main\n"); 
     return 0; 
} 

Vì vậy, đang bối rối ...

+1

Ai nói bạn không thể có con trỏ hàm trong cấu trúc trong 'C'? – detly

+2

Có, có vẻ như bạn đang pha trộn mọi thứ. Con trỏ chức năng được cho phép, không tự hoạt động. –

+0

gọi lại là một con trỏ-to-chức năng với 0 tham số trả về int. C sẽ cho phép bạn gán cho gọi lại bằng cách tham chiếu bất kỳ hàm nào khớp với chữ ký hàm đó. Việc sử dụng danh sách khởi tạo là những gì mới và đặc biệt ở đây. Tuyên bố printf hợp lệ C, nhưng không tốt. Nó là khó hiểu là để ý định và nếu bạn nhìn thấy nó xuống cách xa định nghĩa struct bạn có thể hoang mang như những gì nó đã và phải đi săn bắn. –

0

Không sao đâu. Trong mã nhân Linux, bạn sẽ tìm thấy nhiều cấu trúc chứa hàm. như:

/* 


* The type of device, "struct device" is embedded in. A class 
* or bus can contain devices of different types 
* like "partitions" and "disks", "mouse" and "event". 
* This identifies the device type and carries type-specific 
* information, equivalent to the kobj_type of a kobject. 
* If "name" is specified, the uevent will contain it in 
* the DEVTYPE variable. 
*/ 
struct device_type { 
     const char *name; 
     struct attribute_group **groups; 
     int (*uevent)(struct device *dev, struct kobj_uevent_env *env); 
     void (*release)(struct device *dev); 
     int (*suspend)(struct device * dev, pm_message_t state); 
     int (*resume)(struct device * dev); 
}; 
+0

Vâng, chúng là con trỏ cho các chức năng - giống nhau, ngoại trừ phải mất một số nỗ lực để khởi tạo chúng, có nguy cơ cố gắng sử dụng chúng khi chúng NULL hoặc không hợp lệ, và chúng có thể thay đổi vào thời gian chạy .. .. –

0

Có thể của nó để khai báo một hàm và định nghĩa hàm là không được phép và đó phải là con trỏ hàm.

Dựa trên cấu trúc được gắn thẻ C99 của nó.

Lokesh V

0

Có thể, nhưng không có lợi thế vốn có trong lập trình C thông thường.

Trong C, tất cả các chức năng đều nằm trong không gian toàn cục, vì vậy bạn không bị ẩn thông tin bằng cách nhét chúng vào một hàm.Ví dụ của paxdiablo là một cách để tổ chức các hàm thành một cấu trúc, nhưng bạn phải xem có phải coi trọng từng cái một để sử dụng nó.

Cấu trúc tổ chức tiêu chuẩn của C là Tệp, với giao diện trong tiêu đề và triển khai trong nguồn.

Đó là cách libc được thực hiện và đó là cách hầu như tất cả các thư viện C được thực hiện.

Trình biên dịch C của trình điều khiển cho phép bạn xác định và triển khai các hàm trong cùng một tệp nguồn và thậm chí triển khai các hàm tĩnh trong tệp tiêu đề. Điều này không may dẫn đến một số nhầm lẫn về những gì xảy ra ở đâu và bạn có thể nhận được các giải pháp bất thường như nhồi nhét các chức năng vào các cấu trúc, các chương trình chỉ nguồn không có tiêu đề, v.v. Bạn mất lợi thế khi tách giao diện khỏi triển khai theo cách đó.

0

Không bạn không thể. Cấu trúc không thể chứa một khai báo chức năng nhưng chúng có thể chứa định nghĩa của một hàm. Cấu trúc chỉ có thể chứa các kiểu dữ liệu, con trỏ, con trỏ đến hàm khác nhau. Bạn có thể làm cho một con trỏ đến một chức năng và sau đó truy cập từ cấu trúc.

#include<iostream> 
#include<cstring> 
using namespace std; 

struct full_name 
{ 
    char *fname; 
    char *lname; 
    void (*show)(char *,char*); 
}; 

void show(char *a1,char * a2) 
{ 
    cout<<a1<<"-"<<a2<<endl; 
} 

int main() 
{ 

struct full_name loki; 
loki.fname="Mohit"; 
loki.lname="Dabas"; 
loki.show=show; 
loki.show(loki.fname,loki.lname); 


return 0; 

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