2010-11-19 54 views
27

結構可以包含函數嗎?結構中的功能

+0

他們可以,但在通常的C編程中沒有固有的優勢。 在C語言中,所有的函數都在全局空間中,所以你不會在函數中隱藏信息而隱藏信息。 paxdiablo的示例是一種將函數組織到結構中的方法,但是您必須看到無論如何都必須解除引用每個函數才能使用它。 C的標準組織結構是文件,標頭中的接口和源中的實現都是 。 這就是libc的完成方式,幾乎所有的C庫都完成了。 – 2017-06-22 21:13:18

回答

33

不,但它們可以包含函數指針。

如果你的目的是做某種形式的多態性在C,那麼是的,這是可以做到:以上

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; 

typedef是爲我工作的一個通用的通信庫中創建一個結構。爲了初始化變量,你會:

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(); 

然後,要調用的函數,是這樣的:

// 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"); 

這樣,單一類型的可用於TCP,SNA,RS232或者甚至運營商皮帶,具有完全相同的界面。

+1

那麼這也是不同的黑/白結構和類之一嗎?因爲據我所知,唯一的區別是結構具有默認公共和類是默認私人 – JoshMachine 2010-11-19 07:41:26

+0

@Josh,我認爲你是公正/私人是C + +結構/聯合之間的唯一區別。這個問題是關於C.我懷疑C++允許函數,因爲'struct xyz {int fn(void); } a;'在g ++中工作得很好。 – paxdiablo 2010-11-19 07:48:47

+0

哦,對了,我沒有看到C標籤。 +1清除疑問! – JoshMachine 2010-11-19 07:57:52

5

編輯清理歧義與使用的數據類型「

不在C. struct類型只能包含數據。

來自ISO C99標準的第6.7.2.1節。

結構或聯合不得含有具有不完整或功能類型(因此, 的結構不應含有自己的一個實例,但也可以包含一個指針到一個實例的本身 ),除了一個構件具有多個名爲成員 的結構的最後一個成員可能具有不完整的數組類型;這樣的結構(以及任何包含,可能是遞歸地包含這種結構的成員的聯合)不應該是數組的結構或元素的成員。

+0

+1指出標準 – Jay 2010-11-19 08:06:38

+0

「包含數據類型」是一個危險的含糊不清(至少是一個C++用戶,他們可以聲明類型) - 「包含數據」似乎更準確。標準中的所有內容都表明了這一點:-)。 – 2010-11-19 08:38:08

0

在C中,結構允許包含數據值而不是函數指針。在C中不允許,但在使用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; 
} 

所以,很迷茫......

+1

誰說你不能在'C'的結構中有函數指針? – detly 2010-11-19 07:08:27

+2

是的,你似乎在混合東西。函數指針是允許的,函數本身不是。 – 2010-11-19 07:08:29

+0

回調是一個指向函數的指針,返回0的參數返回int。 C將允許您通過引用分配回調函數匹配 函數簽名的任何函數。 初始化列表的使用在這裏是新的和特殊的。 printf語句是有效的C,但不是很好的樣式。它對 意圖感到困惑,如果你看到遠離結構定義的方式,你可能會對它是什麼以及不得不去狩獵感到困惑。 – 2017-06-22 21:06:23

0

它的所有權利。 在linux內核代碼中,你會發現很多結構都包含函數。 如:

/* 


* 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

嗯,它們是函數的指針 - 幾乎相同,除了它需要一些努力來初始化它們,當它們爲NULL或否則無效時試圖使用它們,並且它們可以在運行時更改。 .. – 2010-11-19 08:39:27

0

是其可能的聲明函數和函數定義是不允許的,應該是這樣的函數指針。

它基於C99標記的結構。

LOKESH V

0

他們就可以了,但在通常的C編程沒有固有的優勢。

在C中,所有函數都在全局空間中,所以你不會通過在函數中將它們摺疊來隱藏信息。paxdiablo的示例是一種將函數組織到結構中的方法,但是您必須看到無論如何都必須解除引用每個函數才能使用它。

C的標準組織結構是文件,標頭中的接口和源中的實現都是 。

這就是libc的完成方式,幾乎所有的C庫都完成了。

現代C編譯器允許您在同一個源文件中定義和實現函數,甚至在頭文件中實現靜態函數。這不幸的是會導致一些混淆,到什麼地方去,你可以得到不尋常的解決方案,比如將函數塞進結構體,沒有頭文件的源代碼程序等等。 你失去了將接口從實現中分離出來的優勢。

0

不可以。結構不能包含函數的聲明,但它們可以包含函數的定義。結構只能包含數據類型,指針,指向不同的函數。你可以指向一個功能,然後從結構訪問。

#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; 

}