4.6 可见度和访问函数
我们现在可以尝试着实现 Circle_draw()
。基于“need to know ”这样的规则信息隐藏要求我们对于每个类使用 3 个文件。 Circle.h
包含抽象数据类型接口;对于一个子类它包含了超类的接口文件以便于这样的声明使得继承的方法可用:
#include "Point.h"
extern const void* Circle; /*new(Circle,x,y,rad)*/
接口文件 Circle.h
被应用程序代码所包含并且对于类的实现;它避免了多次包含所引发的错误。
一个环的表示在第二个头文件中声明, Circle.r
。对于子类它包含了超类的表示文件以便于我们能够通过扩展超类派生出子类的表示:
#include "Point.r"
struct Circle{const struct Point _;int rad;};
子类需要超类的表示去实现继承: struct Circle
包含了一个 const struct Point
。这个点确定不是只读的 - move()
将改变它的坐标 - 但是 const
限定词防止了意外的覆盖它的组成部分。表示文件 Circle.r
仅仅被类的实现所包含;仍然受到多重调用的保护。
最终,对一个环的实现对于类,对于对象管理,被在包含接口和表示文件的原文件 Circle.c
中所定义:
#include "Circle.h"
#include "Circle.r"
#include "new.h"
#include "new.r"
static void Circle_draw(const void * _self)
{
const struct Circle* self=_self;
printf("circle at %d rad %d\n",self->_.x,self->_.y,self->rad);
}
在 Circle_draw()
中,对于环我们通过子类部分使用“可见的名字”. 来读取点部分。从信息隐藏的角度看这并不是一个好的注意。然而读取坐标值不应该产生重大的问题,我们决不能确保在其他情形下,一个子类的实现不去直接的欺骗和修改它的父类的一部分,因此带着其不变量去玩一场浩劫。
效率要求一个子类能直接的访问到其超类的组成部分。信息隐藏和可维护性原则要求一个超类从它的子类上尽可能好的隐藏对它自己的表示。如果我们后面做出选择,我们应该能够提供对这些子类被允许查看超类所有组成部分访问函数,并且对于这些组成部分提供更正函数,即,便要子类去做修改。
访问和修改函数时静态链接的方法。如果我们对于超类在表示文件中声明了他们,超类仅包含在子类的实现中,我们可以使用宏,如果宏使用每个参数仅以此则副作用没有问题。作为一个例子,在 Point.r
中,我们定义了下面的访问宏:
#define x(p) (((const struct Point*)(p))->x)
#define y(p) (((const struct Point*)(p))->y)
这些宏对于任何以 struct Point
开始对象能够被应用于一个指针,也就是说,对于对象,从我们的点的任何子类。这项技术即为,上抛我们的点到超类并引用我们感兴趣的部分。 const
在抛得过程中对结果的分配。如果 const
被忽略
#define x(p) (((struct Point*)(p))->x)
一个宏调用 x(p)
产生一个能成为分配的目标的 l-value
,一个好点的修改函数最好是一个宏的定义
#define set_x(p,v) (((struct Point*)(p))->x=(v))
此定义产生一个分配。
在子类实现的外部对于访问和修改函数我们仅仅使用静态链接的方法。我们不能够求助于宏,因为对于宏引用超类的内部表示是不可见的。对于包含进应用程序的信息隐藏并不提供表示文件 Point.r
而实现。
宏定义揭示了,然而,一旦一个类的表示可用,信息隐藏能够被很容易的击败。这里有一个方式更好的隐藏 struct Point
。在超类的实现中,我们使用正常的定义:
struct Point{
const void* class;
int x,y;
};
对于子类的实现我们提供下面的看起来不透明的版本:
struct Point{
const char _[sizeof(struct {const void* class; int x,y;})];
};
这个结构体像先前拥有相同的大小,但是我们不能够读取也不能够写它的组成部分因为他们被隐藏在一个匿名的内部结构中。重点是这两种声明必须包含相同的组成部分的声明并且这在没有与处理器的情况下是很难维持的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论