Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C使用typedef结构时的设计样式_C_Design Patterns - Fatal编程技术网

C使用typedef结构时的设计样式

C使用typedef结构时的设计样式,c,design-patterns,C,Design Patterns,如果在源文件中使用typedef结构,并且外部系统需要通过接口连接到此类,那么处理输入的正确方法是什么 例如,如果子系统中的源文件 typedef struct { double latitude; double longitude; } GPSLocation; 外部类希望使用以下函数 void setupGPSSystem(char* navigationSystem, GPSLocation *start, GPSLocation *destination) 假设我使用

如果在源文件中使用typedef结构,并且外部系统需要通过接口连接到此类,那么处理输入的正确方法是什么

例如,如果子系统中的源文件

typedef struct
{
    double latitude;
    double longitude;
}
GPSLocation;
外部类希望使用以下函数

void setupGPSSystem(char* navigationSystem, GPSLocation *start, GPSLocation *destination)
假设我使用接口抽象了它,并有一个外部类调用的函数。该函数应该采用GPSLocation类型的参数(从而强制外部系统
#包括存在结构的源文件,而不是现在的外部结构),还是最好保持子系统中使用的所有typedef结构,从而具有如下接口函数

void setupGPSSystem(char* navigationSystem, double startLat, double startLong, double destinationLat, double destinationLong)

GPSLocation
类型属于API,并且应该位于头文件(以
.h
结尾的文件)中,API的用户将
包括

类型属于API,并且应该位于头文件(以
.h
结尾的文件)中,API的用户将
#包括

您可以在接口的公共头中声明类型,并将结构定义隐藏在实现源文件中。因此,您可能有:

gps_系统.h:

typedef struct GPSLocation GPSLocation;

void setupGPSSystem(char* navigationSystem, GPSLocation *start, GPSLocation *destination);
gps_系统.c:

struct GPSLocation
{
    double latitude;
    double longitude;
}

这样,您就可以两全其美:用户可以在接口中使用有意义的类型,而实现是私有的。

您可以在接口的公共头中声明类型,并将结构定义隐藏在实现源文件中。因此,您可能有:

gps_系统.h:

typedef struct GPSLocation GPSLocation;

void setupGPSSystem(char* navigationSystem, GPSLocation *start, GPSLocation *destination);
gps_系统.c:

struct GPSLocation
{
    double latitude;
    double longitude;
}
这样,您就可以两全其美:您的用户可以在界面中使用有意义的类型,而您的实现是私有的。

您的子系统可能(应该)有一个头文件,定义其他人用来访问您的系统(API)的函数原型。在这个头文件中定义结构并没有什么错,包括typedef。事实上,这是很常见的。这样,如果您的函数原型遵循该原型,您就可以了。因此:

#ifndef MYSUBSYSTEM_H
#define MYSUBSYSTEM_H

typedef struct
{
    double latitude;
    double longitude;
}
GPSLocation;

void setupGPSSystem(char* navigationSystem, 
                     GPSLocation *start, GPSLocation *destination);

#endif
这将是一个很好的头球。在你的函数中间的新行使它适合。代码>#将
包含在链接到您的系统并设置好的代码中。

您的子系统可能(应该)有一个头文件,定义其他人用来访问您的系统(API)的函数原型。在这个头文件中定义结构并没有什么错,包括typedef。事实上,这是很常见的。这样,如果您的函数原型遵循该原型,您就可以了。因此:

#ifndef MYSUBSYSTEM_H
#define MYSUBSYSTEM_H

typedef struct
{
    double latitude;
    double longitude;
}
GPSLocation;

void setupGPSSystem(char* navigationSystem, 
                     GPSLocation *start, GPSLocation *destination);

#endif

这将是一个很好的头球。在你的函数中间的新行使它适合。代码>#包括
,在链接到您的代码中,您已设置。

您必须让用户
#包括
一个标题,其中包含接口功能的原型,因此,您也可以将结构定义粘贴在该标题中。

您必须让用户
#为您的接口函数包含一个带有原型的标题,因此您也可以将结构定义粘贴在该标题中。

提到“类”可能不是一个热门主意在一个关于C语言结构的问题:-)只是为了避免任何可能的混淆,例如,C++。 您会问“函数是否应该采用GPSLocation类型的参数(从而强制外部系统#包括存在结构的源文件,…”

您编写的函数不接受GPSLocation类型的参数;它接受指向GPSLocation结构(即地址)的指针类型的参数,这是一件非常不同和美妙的事情

而且,非常正确地说,除了定义GPSLocation的头文件(.h)之外,您没有强迫任何人包含任何内容。这是因为在您的函数项(据我所知)中,您期望指向实例化err的指针,这些结构的副本(开始和结束)当它们存在于调用程序中时。您将通过它们的地址/指针获得每个按引用传递的结构的成员

到目前为止,这是用C传递结构的最好方法——通过指向调用程序的那些结构副本的指针


<>忘记你所给的第二个选择。永远!

< P> >在C语言结构的问题中提到“类”可能不是一个很好的想法:-为了避免任何可能的混淆,比如说C++。 您会问“函数是否应该采用GPSLocation类型的参数(从而强制外部系统#包括存在结构的源文件,…”

您编写的函数不接受GPSLocation类型的参数;它接受指向GPSLocation结构(即地址)的指针类型的参数,这是一件非常不同和美妙的事情

而且,非常正确地说,除了定义GPSLocation的头文件(.h)之外,您没有强迫任何人包含任何内容。这是因为在您的函数项(据我所知)中,您期望指向实例化err的指针,这些结构的副本(开始和结束)当它们存在于调用程序中时。您将通过它们的地址/指针获得每个按引用传递的结构的成员

到目前为止,这是用C传递结构的最好方法——通过指向调用程序的那些结构副本的指针


忘记你给出的第二个选择。永远!

在设计模块时,你需要决定此模块的用户是否需要直接访问结构中的字段,这将决定你最终定义结构的位置。我将描述几个不同的场景:

1.用户(模块的用户)将直接在您的结构中操作GPS数据。您别无选择,只能将结构定义在头文件(.h)中作为API的一部分。优点是该技术简单,并提供
struct GPSLocation_private
{
    GPSLocation gps_public;

    int field_0;
    int field_1;
};

/** Convert from the public version of the gps object object to the private. */
#define gps_get_private(gps_public)  ((struct GPSLocation_private *)(((char *)(gps_public)) - offsetof(struct GPSLocation_private, gps_public)))

void gps_new(GPSLocation **gps)
{
    struct GPSLocation_private *priv;

    priv = malloc(sizeof(struct GPSLocation_private));

    if (priv)
    {
        priv->field_0 = 1234;
        priv->field_1 = 4567;
        priv->gps_public.latitude = 1111;
        priv->gps_public.longitude = 2222;
        gps = &priv->gps_public;
    }
    else
    {
        *gps = NULL;
    }    
}

void gps_set(GPSLocation *gps, double latitude, double longitude)
{
    struct GPSLocation_private *priv;

    priv = gps_get_private(gps);

    /*  Do stuff with 'priv'. */
}

void gps_delete(GPSLocation *gps)
{
    struct GPSLocation_private *priv;

    priv = gps_get_private(gps);
    free(priv);
}