psl_87 发表于 2014-12-17 20:46:03

对于全局的结构体变量怎么用接口函数封装?

前两天看了到了个关于如何避免使用全局变量的帖子:
http://www.amobbs.com/thread-5598120-1-1.html

收益颇多,用get_xxx和set_xxx接口函数把全局变量封装后感觉程序清爽多了

但是如果这个全局变量是结构体变量感觉有点问题,如果是只对这个结构体变量中一个成员进行读写操作好像不太方便啊,需要先对整个结构体变量操作,然后再操作里面的成员

对全局结构体变量进行封装有什么更好的方法么?

dxgdsx 发表于 2014-12-17 21:41:58

对get_xxx和set_xxx接口函数的参数列表做些改动,增加一些标志来识别所需的成员变量。

psl_87 发表于 2014-12-17 22:22:54

dxgdsx 发表于 2014-12-17 21:41
对get_xxx和set_xxx接口函数的参数列表做些改动,增加一些标志来识别所需的成员变量。 ...

我也这么想过,但这不是得增加几条判断语句么?有没有更高效的访问方法?

kanprin 发表于 2014-12-17 22:43:31

有个参数叫 void *

kanprin 发表于 2014-12-17 22:51:52

不好意思,应该是说,修改结构体中的某个成员,最好还是指针访问比较简单。此时采用获取结构体指针的方式方便些。

heyueming0 发表于 2014-12-17 22:54:22

参数什么的,最喜欢用全局变量了……

dxgdsx 发表于 2014-12-18 09:38:39

kanprin 发表于 2014-12-17 22:51
不好意思,应该是说,修改结构体中的某个成员,最好还是指针访问比较简单。此时采用获取结构体指针的方式方 ...

用指针应该是最方便的,但是同时也带来了“全局变量”类似的后果的。不太可控,需要编的人格外小心。我是这么理解的。

dxgdsx 发表于 2014-12-18 09:47:37

本帖最后由 dxgdsx 于 2014-12-18 09:56 编辑

psl_87 发表于 2014-12-17 22:22
我也这么想过,但这不是得增加几条判断语句么?有没有更高效的访问方法? ...

我觉得主要取决于是:1、以最快速度访问;2、尽可能保护全局变量,维护可读性。
如果是1,那么用指针是最快的,但是要小心使用。如果是2,那么要确保接口函数是唯一访问读写的通道,不存在其他任何方式(包括指针)。
其实可以不用判断语句就可以实现的。

Gorgon_Meducer 发表于 2014-12-18 10:21:13

请举出具体例子,我告诉你怎么弄。

psl_87 发表于 2014-12-18 12:39:14

Gorgon_Meducer 发表于 2014-12-18 10:21
请举出具体例子,我告诉你怎么弄。

谢谢傻孩子,比如我在test1.c文件里定义了一个全局结构体变量,以及相应的接口函数:

static volatile GLOBAL var;

GLOBAL get_var(void)
{
        return var;
}
void set_var(GLOBAL data)
{
        var = data;
}

然后在test1.h里定义GLOBAL结构体:
typedef struct
{
      int a;
      char b;
      double c;
} GLOBAL

现在我想在test2.c文件里操作GLOBAL.b这个成员,按我的简单思路就是得先读取整个结构体变量,然后对成员b时行操作:
GLOBALtemp;

temp = get_var();
temp.b = 55;
set_var(temp);


按我这方法,对结构体一个成员操作就得先对整个结构体变量进行操作,感觉效率很低,不知道种情况的标准处理是怎么做的?

Gorgon_Meducer 发表于 2014-12-18 13:33:58

本帖最后由 Gorgon_Meducer 于 2014-12-18 13:35 编辑

psl_87 发表于 2014-12-18 12:39
谢谢傻孩子,比如我在test1.c文件里定义了一个全局结构体变量,以及相应的接口函数:




这种方式是不可以的,直接破坏了封装。
按道理来说,这个结构体的内容对外界应该是保密的,或者说应该是保护的。需要用掩码结构体来进行保护。
简单说,针对你举的这个例子,你不可以直接把这个结构体返回出去。
你应该直接针对结构体里面的成员建立set和get方法。这个叫做property,一个从C#借来的概念。

如果你的这个结构体是类,用户可以建立多个类的实例,则玩法是另外的样子。

security 发表于 2014-12-18 13:45:53

psl_87 发表于 2014-12-18 12:39
谢谢傻孩子,比如我在test1.c文件里定义了一个全局结构体变量,以及相应的接口函数:




你这样等于没有封装了,又暴露了结构体的属性及方法,又名成员变量和成员函数。
只不过如今,更喜欢称为属性和方法。

最好的封装是隐藏全部的属性,不暴露出来。
对外只提供对象的构造和析构接口,以及公有接口,例如set/get接口

属性通过set/get接口来访问
比如增加一个set接口,来设置这里的b属性。

234918154 发表于 2014-12-18 13:59:00

security 发表于 2014-12-18 13:45
你这样等于没有封装了,又暴露了结构体的属性及方法,又名成员变量和成员函数。
只不过如今,更喜欢称为 ...

你这么一说不就变成C++里面的理论了

security 发表于 2014-12-18 14:02:02

本帖最后由 security 于 2014-12-18 14:05 编辑

234918154 发表于 2014-12-18 13:59
你这么一说不就变成C++里面的理论了

是的,我说的是OOP的思想
但实际项目中,可以不走这条路,但set/get接口,不对,严格应称为set/get方法
是通用的

只是这里不需要返回整个结构体
只需做小粒度的处理,即针对b属性,做相应的set/get方法。

psl_87 发表于 2014-12-18 14:46:25

谢谢楼上几位大神的解释,大概明白问题在哪,也就是说对于结构体变量,最好对里面的成员做set/get方法

但这样成员变量多的时候,每个都去做接口函数,感觉也挺费劲啊

McuPlayer 发表于 2014-12-18 14:54:54

大家还记得win系统编程时候的HANDLE吗,其实他也是个指针,称之为句柄,是因为它所指向的结构体是不开放的,而且系统升级后可能结构体也变化,这样写应用程序的人不会为了适应N个系统写N套代码了

security 发表于 2014-12-18 15:24:09

McuPlayer 发表于 2014-12-18 14:54
大家还记得win系统编程时候的HANDLE吗,其实他也是个指针,称之为句柄,是因为它所指向的结构体是不开放的 ...

实际上Windows的HANDLE不是指针
而是类似如下机制:一个指针的索引ID值,通过这个HANDLE,在句柄表中,找到结构体的实际指针,再去访问结构体。

security 发表于 2014-12-18 15:27:55

psl_87 发表于 2014-12-18 14:46
谢谢楼上几位大神的解释,大概明白问题在哪,也就是说对于结构体变量,最好对里面的成员做set/get方法

但 ...

那也许你就要考虑一个哲学问题:
设计上是不是需要暴露这么多属性
真的有必要让这么多属性,在外面都可以操作吗

tian_zi 发表于 2014-12-18 15:28:19

前不久也发帖咨询ucos里面怎么减少全局变量使用,现在基本都是把变量封装成结构体,但是完全不用全局变量还是做不到。但结构体作为隐性封装外部看不到,只看到对象的构造和析构接口移植维护找变量感觉好麻烦。。。

security 发表于 2014-12-18 15:34:09

tian_zi 发表于 2014-12-18 15:28
前不久也发帖咨询ucos里面怎么减少全局变量使用,现在基本都是把变量封装成结构体,但是完全不用全局变量还 ...

可以有Public属性的,贴上这标签,标志这属于公开的秘密。
减少全局变量,我想更多的是指:
减少全局变量的静态定义,这样在程序的生命周期内,一直占着茅坑,即便,不拉翔的话。
换句话说,全局变量,应尽可能多的生在堆上,用到时new,用完,销毁回收delete。

tian_zi 发表于 2014-12-18 15:51:57

security 发表于 2014-12-18 15:34
可以有Public属性的,贴上这标签,标志这属于公开的秘密。
减少全局变量,我想更多的是指:
减少全局变量 ...

都是C++编程思想

ijlc1314 发表于 2014-12-19 09:36:24

我现在的做法是,使用 static去定义结构体,对用户开放使用结构体封装的set/get接口,使用函数指针实现,set/get的返回类型为bool,方便用户检查访问成功(true)或是失败(false)

使用的时候是这样的:

uint16_t a;
inf_name *pName = (inf_name *)inf_name_new();

if ( pName->get.A( &a ) )
{
    //!< ...........
}

fengyunyu 发表于 2014-12-19 09:39:39

这个一般是定义好接口函数,传递指针给调用的。

ijlc1314 发表于 2014-12-19 09:39:50

把一个模块或功能的数据和函数(行为)整合到一起,对工作会方便很多

Gorgon_Meducer 发表于 2014-12-19 10:36:29

psl_87 发表于 2014-12-18 14:46
谢谢楼上几位大神的解释,大概明白问题在哪,也就是说对于结构体变量,最好对里面的成员做set/get方法

但 ...

你最后问的问题其实导出了一个模块封装原则:最小公开原则——简单说就是默认全部都不公开,当别人确实需要
用某个东西的时候,经过多方论证,确确实实必须开放某些部分,则应该“勉为其难”的开放满足他功能的最小信息。

zhuyi 发表于 2014-12-19 10:37:13

看具体项目大小和资源多少吧,都封装起来,安全了,但代码多得一大堆,而且也不见得会清爽,因为每个成员都要读写,你一个几十K的资源搞这也搞不了,再这样搞就直接上C++了,那个oopc宏,折腾来折腾去只有开堆才好用,同样耗空间,最后还是放弃。。。不过里面的typedef用得蛮巧妙的

ZY521798 发表于 2014-12-19 14:45:00

感觉接触过c++和java后,现在看这个set/get方法就好理解多了。通过这两个接口对类(结构体)中的数据进行操作,将其中的数据保护起来,外部无权对其操作。
页: [1]
查看完整版本: 对于全局的结构体变量怎么用接口函数封装?