C 中的 Get 和 Set ("private") 缺点?
Get and Set ("private") in C disadvantages?
我想在 C 中创建一个结构,任何人都不能直接访问它的数据,只能像在面向对象中那样通过获取和设置。我的解决方案是这样的:
Point.h
#ifndef POINT_H
#define POINT_H
typedef struct point Point;
Point *CreatePoint(int x, int y);
int Point_GetX(Point *point);
void Point_SetX(Point *point, int x);
int Point_GetY(Point *point);
void Point_SetY(Point *point, int y);
void DeletePoint(Point **p);
#endif /* POINT_H */
Point.c
#include "Point.h"
struct point{
int x, y;
};
Point *CreatePoint(int x, int y){
Point *p = malloc(sizeof(Point));
if (p == NULL) return NULL;
p->x = x;
p->y = y;
return p;
}
int Point_GetX(Point *point){
return point->x;
}
void Point_SetX(Point *point, int x){
point->x = x;
}
int Point_GetY(Point *point){
return point->y;
}
void Point_SetY(Point *point, int y){
point->y = y;
}
void DeletePoint(Point **p){
if (*p != NULL){
free(*p);
*p = NULL;
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "Point.h"
int main(){
Point *p = CreatePoint(2, 6);
if (p == NULL) return EXIT_FAILURE;
/*
p->x = 4; "error: dereferencing pointer
p->y = 9; to incomplete type"
*/
Point_SetX(p, 4);
Point_SetY(p, 9);
printf("POINT(%d,%d)", Point_GetX(p), Point_GetY(p));
DeletePoint(&p);
return EXIT_SUCCESS;
}
当然,我绝不会为了一个简单的观点而对所有这一切进行说明,但这就是我的想法。我想知道这样做会出现什么问题,我是否应该这样做,以及是否可以这样做,如果这不是一个聪明的方法(我应该只选择 c++ xD)。
这样做的原因是我正在做一个小项目,但稍后我可能会更改一些数据结构和算法,所以如果我这样做,我只需要更改 Point.c 在这种情况下,而不是每一个我会去的地方
point->x = new_x
例如
基本上,我是在尝试做 C++ 做的事情吗?或者可以在 C 中执行此操作吗?或者没有,有缺点吗?或者这根本不是 C 的本意?哈哈
My solution was something like [this]
这是C中信息隐藏的经典方案。唯一缺少的是 DestroyPoint
,一个用于释放您使用 malloc
.
分配的点结构的函数
I want to know what could go wrong by doing this, whether I should be doing this or not, and if it's OK to do this.
这是一种安全的方法,只要您接受它的缺点,如下所述。
[is there] a disadvantage?
是的,有:这种方法仅限于动态分配您隐藏其内部的数据结构。你不能这样做:
Point p; // This fails, because `Point` is a forward declaration.
int x = Point_GetX(&p);
类似地,Point
的数组是禁止的;将 Point
嵌入其他 struct
也是不可能的。
Am I trying to do what C++ does?
不是真的。您的方法类似于 Objective-C,因为 C++ 没有仅在动态存储中分配对象的限制,而 Objective-C 有。不过,此限制似乎不会给 Objective-C 程序员带来太多问题。
您描述的这种封装策略在 C 库中使用得比较频繁。完全没问题。
但是请注意,它是由 约定 封装的,而不是由语言本身强制执行的,因为对 private
成员的访问是在 C++ 中强制执行的。在 C 中,虽然 you 不提供 struct point
的完整声明,但任何客户端代码都可以这样做,使其能够访问实例的成员。
需要多少个点结构实例?
就一个还是几个?
无论如何,function:CreatePoint() 在向世界提供点数据的同时也放弃了农场。
代码需要向世界隐藏点(及其字段)的实际内容。
那么只有访问函数可以访问点。
如果点需要有多个实例,
然后 CreatePoint() returns 一些整数,可以在对访问器函数的其他调用中使用到 select 正确的点。
CreatePoint 函数会执行类似于 malloc() 的操作来为新点获取空间。
应该有销毁点的功能(在table点中标记销毁?)
printf("POINT(%d,%d)", Point_GetX(&p), Point_GetY(&p));
应该是:
printf("POINT(%d,%d)", Point_GetX(p), Point_GetY(p));
我想在 C 中创建一个结构,任何人都不能直接访问它的数据,只能像在面向对象中那样通过获取和设置。我的解决方案是这样的:
Point.h
#ifndef POINT_H
#define POINT_H
typedef struct point Point;
Point *CreatePoint(int x, int y);
int Point_GetX(Point *point);
void Point_SetX(Point *point, int x);
int Point_GetY(Point *point);
void Point_SetY(Point *point, int y);
void DeletePoint(Point **p);
#endif /* POINT_H */
Point.c
#include "Point.h"
struct point{
int x, y;
};
Point *CreatePoint(int x, int y){
Point *p = malloc(sizeof(Point));
if (p == NULL) return NULL;
p->x = x;
p->y = y;
return p;
}
int Point_GetX(Point *point){
return point->x;
}
void Point_SetX(Point *point, int x){
point->x = x;
}
int Point_GetY(Point *point){
return point->y;
}
void Point_SetY(Point *point, int y){
point->y = y;
}
void DeletePoint(Point **p){
if (*p != NULL){
free(*p);
*p = NULL;
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include "Point.h"
int main(){
Point *p = CreatePoint(2, 6);
if (p == NULL) return EXIT_FAILURE;
/*
p->x = 4; "error: dereferencing pointer
p->y = 9; to incomplete type"
*/
Point_SetX(p, 4);
Point_SetY(p, 9);
printf("POINT(%d,%d)", Point_GetX(p), Point_GetY(p));
DeletePoint(&p);
return EXIT_SUCCESS;
}
当然,我绝不会为了一个简单的观点而对所有这一切进行说明,但这就是我的想法。我想知道这样做会出现什么问题,我是否应该这样做,以及是否可以这样做,如果这不是一个聪明的方法(我应该只选择 c++ xD)。 这样做的原因是我正在做一个小项目,但稍后我可能会更改一些数据结构和算法,所以如果我这样做,我只需要更改 Point.c 在这种情况下,而不是每一个我会去的地方
point->x = new_x
例如
基本上,我是在尝试做 C++ 做的事情吗?或者可以在 C 中执行此操作吗?或者没有,有缺点吗?或者这根本不是 C 的本意?哈哈
My solution was something like [this]
这是C中信息隐藏的经典方案。唯一缺少的是 DestroyPoint
,一个用于释放您使用 malloc
.
I want to know what could go wrong by doing this, whether I should be doing this or not, and if it's OK to do this.
这是一种安全的方法,只要您接受它的缺点,如下所述。
[is there] a disadvantage?
是的,有:这种方法仅限于动态分配您隐藏其内部的数据结构。你不能这样做:
Point p; // This fails, because `Point` is a forward declaration.
int x = Point_GetX(&p);
类似地,Point
的数组是禁止的;将 Point
嵌入其他 struct
也是不可能的。
Am I trying to do what C++ does?
不是真的。您的方法类似于 Objective-C,因为 C++ 没有仅在动态存储中分配对象的限制,而 Objective-C 有。不过,此限制似乎不会给 Objective-C 程序员带来太多问题。
您描述的这种封装策略在 C 库中使用得比较频繁。完全没问题。
但是请注意,它是由 约定 封装的,而不是由语言本身强制执行的,因为对 private
成员的访问是在 C++ 中强制执行的。在 C 中,虽然 you 不提供 struct point
的完整声明,但任何客户端代码都可以这样做,使其能够访问实例的成员。
需要多少个点结构实例?
就一个还是几个?
无论如何,function:CreatePoint() 在向世界提供点数据的同时也放弃了农场。
代码需要向世界隐藏点(及其字段)的实际内容。
那么只有访问函数可以访问点。
如果点需要有多个实例,
然后 CreatePoint() returns 一些整数,可以在对访问器函数的其他调用中使用到 select 正确的点。
CreatePoint 函数会执行类似于 malloc() 的操作来为新点获取空间。
应该有销毁点的功能(在table点中标记销毁?)
printf("POINT(%d,%d)", Point_GetX(&p), Point_GetY(&p));
应该是:
printf("POINT(%d,%d)", Point_GetX(p), Point_GetY(p));