2010-11-19 56 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; 

}