我听说在设计 BSD 套接字库时,C 编程缺少导致我们今天的设计的特定模式或功能。
例如,struct socketaddr_in
在传递给 bind
等系统调用时被转换为 struct socketaddr
。
来自 GNU libc 头文件:
/* POSIX.1g specifies this type name for the `sa_family' member. */
typedef unsigned short int sa_family_t;
/* This macro is used to declare the initial common members
of the data types used for socket addresses, `struct sockaddr',
`struct sockaddr_in', `struct sockaddr_un', etc. */
#define __SOCKADDR_COMMON(sa_prefix) \
sa_family_t sa_prefix##family
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
/* Structure describing a generic socket address. */
struct sockaddr
{
__SOCKADDR_COMMON (sa_); /* Common data: address family and length. */
char sa_data[14]; /* Address data. */
};
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
/* Internet address. */
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
示例程序:
int main(int argc, char *argv[]) {
...
// Initialize the server address
struct sockaddr_in serv_addr;
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr = (struct sockaddr_in) {
.sin_port = htons(port),
.sin_family = AF_INET ,
.sin_addr.s_addr = INADDR_ANY
};
// Bind the server address to the TCP/IP socket
int status = bind(server_socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
...
}
我想不出还有什么其他方法可以让这个通用接口(interface)到位。有什么想法吗?
最佳答案
您可以使用委托(delegate)模式来支持 C 中的一种继承形式。它看起来很漂亮,它是通用的,但它非常重量级:有很多潜在的故障点,需要一些堆分配等。我想他们确实做到了不想让 OS API 有这种重量?
举个例子
struct ShapeDelegate {
double (*getSurfaceArea)(void* data);
int (*isInside)(void* data, double x, double y);
void (*destroy)(void* data);
}
struct Shape {
void* data;
struct ShapeDelegate delegate;
}
double Shape_getSurfaceArea(Shape* self) {
return self->delegate.getSurfaceArea(self->data);
}
int Shape_isInside(Shape* self, double x, double y) {
return self->delegate.isInside(self->data, x, y);
}
void Shape_destroy(Shape* self) {
if (self->delegate.destroy != NULL)
self->delegate.destroy(self->data);
}
现在,比方说,你想要一个 Circle 作为 Shape 的实现
struct CircleData {
double x, y, r;
}
double Circle_getSurfaceArea(void* data) {
CircleData* self = (CircleData*)data;
return 2 * M_PI * self->r * self->r;
}
int Circle_isInside(void* data, double x, double y) {
double dist;
CircleData* self = (CircleData*)data;
dist = sqrt(sqr(x - self->x) + sqr(y - self->y));
return dist < self->r;
}
void Circle_destroy(void* data) {
free(data);
}
struct ShapeDelegate Circle_ShapeDelegate {
Circle_getSurfaceArea,
Circle_isInside,
Circle_destroy
};
你需要某种构造器
void
Shape_initAsCircle(Shape* self, double x, double y, double r) {
CircleData* data;
data = (CircleData*)malloc(sizeof(CircleData));
data->x = x, data->y = y, data->r = r;
self->data = data;
self.delegate = Circle_ShapeDelegate;
}
关于c - 替代 C 中的 "subclassing"结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16867583/